- 在线时间
- 155 小时
- 最后登录
- 2013-4-28
- 注册时间
- 2012-5-7
- 听众数
- 5
- 收听数
- 0
- 能力
- 2 分
- 体力
- 2333 点
- 威望
- 0 点
- 阅读权限
- 50
- 积分
- 913
- 相册
- 1
- 日志
- 26
- 记录
- 52
- 帖子
- 291
- 主题
- 102
- 精华
- 0
- 分享
- 6
- 好友
- 84
升级   78.25% TA的每日心情 | 开心 2013-4-28 12:11 |
|---|
签到天数: 160 天 [LV.7]常住居民III
 群组: 数学软件学习 |
1、连接数据库+ E# S' E X- v) ~ ]$ |" t/ t
" p/ s; g! o- N4 v7 M1)直接连接数据库和创建一个游标(cursor)3 U: l+ }9 Y b9 m
1 cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=me WD=pass')2 R- ]: d& g) a! s3 J
2 cursor = cnxn.cursor()
7 @* Z) V* h- U
5 P/ I' y Z0 t/ P2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。
! w$ ^( Y* P1 Z8 Y% b5 B# ^1 cnxn = pyodbc.connect('DSN=test WD=password')6 o- b F" T* f8 |& ~
2 cursor = cnxn.cursor()
- @0 A) E$ C- y( w
4 E' y9 a1 S+ [$ @5 P9 \关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节
% G, |( ~; l4 ?
' q* h5 f0 V/ C3 U$ O6 ?, e P2、数据查询(SQL语句为 select ...from..where)! y; N- x% F4 ]3 y
8 h& Q; M4 a, u0 a& w* S2 b1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。
9 ^8 q! U7 B7 s# S1 cursor.execute("select user_id, user_name from users")
3 ^5 [0 k- A* I$ q: w/ S2 row = cursor.fetchone()# ?: p5 M1 m. E8 p0 |0 x
3 if row:
9 H2 ]4 g- ?! J: p4 print row& ?* Z4 r3 H: ^5 R4 K( i
: w6 V' z) O$ z8 P( \
2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。+ {; ?6 O, m) e T
1 cursor.execute("select user_id, user_name from users")
6 s, S: o2 g+ l' M. z2 row = cursor.fetchone()
# O7 k1 ?. u) I8 N3 print 'name:', row[1] # access by column index
% q, Y. p" T2 K. `# _2 S4 print 'name:', row.user_name # or access by name" d2 J, V3 O; G% i
4 K) F/ v! h6 T& R+ M" D
3)如果所有的行都被检索完,那么fetchone将返回None. ?" X, X7 F" R& c
1 while 1:& _ N0 w' B9 p1 H9 r% a3 K
2 row = cursor.fetchone(). d7 y$ x5 g2 W9 s: Z
3 if not row:5 ^; b/ h4 [( p' A5 [
4 break: W6 H2 s' h3 ^2 t
5 print 'id:', row.user_id
8 g) V! t. v! c4 o$ D; s
y, J4 E! A) |" ~6 R3 ~4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)! |1 h' M5 K* u1 \. S; R) R! ? d
1 cursor.execute("select user_id, user_name from users")# {0 ]$ g7 U: W3 B1 \- L8 d7 B+ t0 V
2 rows = cursor.fetchall()% l" c9 j& u R9 o1 F" B4 n, D
3 for row in rows:
7 ?' @3 |8 ?4 x. K4 print row.user_id, row.user_name
. P( [7 ~% {/ l) A- k w6 G. e6 u: n% O5 Q }: `2 l
5)如果你打算一次读完所有数据,那么你可以使用cursor本身。
. r+ s0 t) i }3 q2 N) E3 _1 cursor.execute("select user_id, user_name from users"):- t+ c6 I) L) U* q! _
2 for row in cursor:( s6 q1 X0 O* H4 e- l) E
3 print row.user_id, row.user_name6 _- b/ L+ I( G
/ r6 G0 x, S' q( C( K
6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:
3 E$ w( i8 l# }1 for row in cursor.execute("select user_id, user_name from users"):# n: T b& i" d) F
2 print row.user_id, row.user_name0 ? ~ l0 t, k" u
, t4 w- U9 ^8 v8 k5 ~# S7 @
7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:% v5 ], l! m$ b' `* g
1 cursor.execute("""' |; Q [$ H4 e" r9 _7 m
2 select user_id, user_name$ b$ K% k- p% i& c8 P
3 from users' a# j# l7 ?/ l9 b. `. U( |
4 where last_logon < '2001-01-01'" U0 e$ A Y0 Q! W
5 and bill_overdue = 'y'
) Z$ R0 u% j& w6 """)
) B( i8 B1 \0 h! n/ A4 j2 N( \' r0 [& y( S! J7 P- }
3、参数7 b2 v* L1 o; e9 h& W
% u( A: I/ j2 ^( `. l) c1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。4 `( ?3 ^7 h# _$ `7 {- n
1 cursor.execute("""
9 ?4 k# n0 R. E3 f2 select user_id, user_name6 Z) S. |- q5 ~
3 from users
: h g' ~ l: i7 L1 ~# [/ B& e4 where last_logon < ?; Z r+ A2 p9 C! o1 s" s
5 and bill_overdue = ?' g2 S J& m1 t
6 """, '2001-01-01', 'y')# z5 Z+ B. i5 ` R% \
' C* a2 E2 F6 O
这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。9 A$ r0 p8 R! N- H3 C" T2 u
# d6 J8 @: C8 j4 e& x3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:
* J% X* Z. F: d: |: V" u5 ?) d1 cursor.execute("""
% R- g- y4 h$ V2 select user_id, user_name% y* s6 L- e6 f6 O2 s# U u
3 from users
9 P2 q8 E# X+ l' B* d$ K4 where last_logon < ?
: A, C+ a# `9 v& l9 L6 C" d4 T' G5 and bill_overdue = ?$ W. V+ f2 _5 l5 Y; S: X
6 """, ['2001-01-01', 'y'])5 i: P6 V$ V; g5 ?' i% ?2 I
" o! G. _( Y( _/ _; {& f' r
1 cursor.execute("select count(*) as user_count from users where age > ?", 21)
( Q0 h z8 q* B1 Q; M+ b) L+ l2 row = cursor.fetchone()9 ?: Q9 t7 ]) \ H& K
3 print '%d users' % row.user_count
/ X/ U/ ^# w6 h9 H- Y) t7 P: z) m
/ ?1 l. ]5 j, V- x; p 7 D( U6 \2 l$ g, Y
3 o9 S w. b4 U! A9 B4、数据插入
% J. v) o- t( z. p: r: Z |; E; I" R2 n9 B
1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。: v- S6 {+ h; q) U4 J: |4 Y0 s
1 cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")7 j5 D3 Q1 L& Y
2 cnxn.commit()
4 e; ]2 o+ ]9 r% \7 U0 Y: ]$ Q/ R0 N ^; g1 j$ \
1 cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library'); x, R F8 E0 t# ]0 A+ o
2 cnxn.commit()8 h; K/ C. [) g1 ]
! l( S- S% U; @( s1 }1 X2 w
注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。/ d$ L3 n/ H" V! L! ]
0 v9 e' W3 X4 }* j; {# [5、数据修改和删除
1 Z* u& k! {7 k
" ]! Y0 J/ P& h2 m1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。
' E3 E$ `3 u" t8 }- Q) F1 cursor.execute("delete from products where id <> ?", 'pyodbc')
' X1 E' N7 n# c' V) P& v2 print cursor.rowcount, 'products deleted'
3 c9 l4 E6 u5 i A: K( P( ]. T3 cnxn.commit()
$ x& v9 X, E* _* m/ I+ D1 p/ ^+ X, ]0 N! l# F* J% E; e' c/ b
2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)2 m \1 R T" D `# Z
1 deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
& R& g* D9 A0 \( c4 N4 x a# |2 cnxn.commit()
T% W5 F6 e9 z9 y: f7 p- c" ]3 A2 t5 w0 r
同样要注意调用cnxn.commit()函数1 E. l& i' m# J! ]$ _5 e& T+ a
' o$ V( K6 R- F2 Y9 S; @6、小窍门
$ q4 F( {- h7 Y! J/ [6 `# S1 [: [1 e# B$ | h5 R+ z, o1 L
1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:
- |6 b$ U3 k1 |1 deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
* G- V( j6 d2 c' x
6 i1 C: f$ v3 a2 e6 H2)假如你使用的是三引号,那么你也可以这样使用:
6 @! Q* j6 L# P6 M6 |1 deleted = cursor.execute("""
; q& S! n) \8 @2 i# t4 d2 delete
: p9 a3 X+ B4 |" h3 from products: y. o9 z' k1 ?7 A
4 where id <> 'pyodbc'. k- |/ p: l1 a( c# M5 t4 H
5 """).rowcount$ R9 }) R j( o
! S" V* t$ [5 J$ V! y) \
3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)3 s" z1 d9 D9 D4 a- W: g
1 row = cursor.execute("select count(*) as user_count from users").fetchone()* u. ?5 X- A: n6 C2 V" r6 e5 m5 i
2 print '%s users' % row.user_count
o( u |: v- ]/ _8 K* [8 H( w6 d# }
4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。
0 p" v Z- s% Q- v' p6 e. u7 k$ b1 count = cursor.execute("select count(*) from users").fetchone()[0]
- |3 q) m W9 i2 C: [# {! k. J2 n2 print '%s users' % count0 I8 i0 T" l \/ o% r
7 |% [6 _" w/ L- P/ K* G
如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。
$ c) b: \8 T- y% A0 p1 maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]3 L+ u2 ]0 v- e0 ~ m" E q. ^4 W
0 `/ [3 C2 G3 r! M5 F
在这个例子里面,如果max(id)返回NULL,coalesce(max(id),0)将导致查询的值为0。 |
zan
|