数学建模社区-数学中国
标题:
pyodbc的简单使用
[打印本页]
作者:
Seawind2012
时间:
2012-7-4 14:30
标题:
pyodbc的简单使用
1、连接数据库
& N8 ]/ T! @' A! K9 I$ w8 B" i
/ e( t; L( U/ Y/ |# t
1)直接连接数据库和创建一个游标(cursor)
3 {+ ?0 @6 q0 v. ~; e J
1 cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=me
WD=pass')
8 p n6 x. W+ [( C+ C. @
2 cursor = cnxn.cursor()
) @; Y' l0 J4 K% A( w
1 H( j( s% b( R2 @/ b! M' e
2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。
+ V; n9 L2 m2 {) g$ R7 i$ x
1 cnxn = pyodbc.connect('DSN=test
WD=password')
2 S% C7 F. l' O6 w
2 cursor = cnxn.cursor()
2 N- X7 d0 \( m _% o- X
# R& ]0 r# `9 p5 N
关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节
! O0 j/ X8 s. N
& F5 _2 {* f' f8 b) q; m9 \
2、数据查询(SQL语句为 select ...from..where)
/ q/ A, q$ ?6 ~, ?/ ?: _
7 c& Z& }- c. h
1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。
% t/ o+ Y# [) ]
1 cursor.execute("select user_id, user_name from users")
5 m4 D, R( h4 J4 R0 k
2 row = cursor.fetchone()
0 @. p; i- _; N4 r+ V4 _0 y0 |8 O' a
3 if row:
& X, w2 q9 t# }* y) n& H/ f1 X1 k; y
4 print row
; }" J/ q: H8 E% g
; v1 z: U5 q: w @' ?. M; ]
2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。
' {3 l; G& s; [) ^- @
1 cursor.execute("select user_id, user_name from users")
( `, z4 o- z: g
2 row = cursor.fetchone()
+ G+ S3 V; |6 i5 e/ ?
3 print 'name:', row[1] # access by column index
% G: _+ L1 ~0 T& L% x
4 print 'name:', row.user_name # or access by name
{5 @6 P: _% N$ D3 t2 u
; S/ z f9 ^. X& s3 Q
3)如果所有的行都被检索完,那么fetchone将返回None.
. W* m+ |& h; s3 {) B
1 while 1:
7 N2 z1 O) H0 ^/ G. l) M/ y
2 row = cursor.fetchone()
0 x/ r/ U8 ]* I* D1 n% D1 c3 W' n
3 if not row:
* f2 @, v6 @3 T
4 break
0 p/ [; T; X/ d# L" J1 a7 l
5 print 'id:', row.user_id
2 X, L' Z6 [" ]
' ^8 c8 G5 _: w1 F
4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)
" e/ b: j5 P) c$ P! E
1 cursor.execute("select user_id, user_name from users")
?6 F4 x) J- V: m6 ?: H2 R
2 rows = cursor.fetchall()
9 y7 i7 O8 O8 |; D
3 for row in rows:
0 @ O- r- z6 s" \1 R+ K: u
4 print row.user_id, row.user_name
4 _, K3 f. u ? A4 d
( E3 H: n& b" P: @6 q
5)如果你打算一次读完所有数据,那么你可以使用cursor本身。
/ e, x k8 @. d; j
1 cursor.execute("select user_id, user_name from users"):
7 p( h8 O* I6 V6 g
2 for row in cursor:
, X* m" t. \: M4 b' e6 Y
3 print row.user_id, row.user_name
$ o- D/ Y7 F; R
' ~/ ?% L* Q. J( A# W& Q
6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:
+ d: A8 O% L& O, W" c
1 for row in cursor.execute("select user_id, user_name from users"):
. a- H& T2 Z1 C+ g
2 print row.user_id, row.user_name
8 E: z6 e0 J" v" ~$ O
% a& Z9 e( Q2 W: B4 e/ q# G1 W. ?3 a
7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:
/ X6 g+ X% I7 I* w$ _) J. r
1 cursor.execute("""
6 L% Z0 k* n. g" e! w+ t: L" I
2 select user_id, user_name
" l! k* e4 c- P5 Q; q, v3 `
3 from users
/ W2 o8 H$ G4 j ]) B
4 where last_logon < '2001-01-01'
D# {9 W& s" h
5 and bill_overdue = 'y'
+ f5 X0 C: C% K! n( h
6 """)
" D* c$ a i" p" I
4 A* Z0 e" k4 O& e
3、参数
2 }) N% p9 ^% p: B4 |
, K6 C8 {+ s, w9 Z$ I4 T5 o
1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。
7 h7 F' d* ^. B, g* b/ C. }
1 cursor.execute("""
' p& X3 V* G3 g
2 select user_id, user_name
" z. Y7 K; r$ \; h8 V
3 from users
6 Q }6 e; I( P* O: Y- g0 M
4 where last_logon < ?
7 L; v5 i, g2 b* _. M- }
5 and bill_overdue = ?
$ b: \* z* D7 u, I9 |
6 """, '2001-01-01', 'y')
: v9 K1 ^4 |8 |
x( l! y. c9 e+ i/ }( ^( t0 B; M9 s
这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。
7 _9 O* K7 F9 R, l
- W& f2 w+ O1 O1 [$ K* b0 e
3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:
! u$ z! C3 o2 L% |5 G3 r0 C
1 cursor.execute("""
* Q* a; l) P+ u' N
2 select user_id, user_name
: }1 @7 `# m7 j0 h8 I
3 from users
' {6 O3 ?1 H% `& o# ?+ K" i2 c
4 where last_logon < ?
% o9 g" D# L' Y+ |
5 and bill_overdue = ?
; |* F; z: G' J$ _
6 """, ['2001-01-01', 'y'])
7 }! W* Z/ W" ]- l7 ]4 w- M _0 P
# O. a' x! A- R4 X$ o0 m( h1 L
1 cursor.execute("select count(*) as user_count from users where age > ?", 21)
- }& I2 g$ s$ }+ _3 k
2 row = cursor.fetchone()
7 {* E2 T5 `" \( G# [/ {- S
3 print '%d users' % row.user_count
: Y% r$ d: Y: `
4 \% f6 Z9 [) d; g$ I5 [
4 Y7 ~# D, k5 T' d
" X" p0 Z. b/ w0 q7 H) F8 H
4、数据插入
" j6 [* H+ P- F S
/ G; b9 w' {4 d' Z3 i
1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。
& j3 X& Y' Z" d; r* m1 \
1 cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")
7 d) r2 [7 M$ L2 R' l4 K
2 cnxn.commit()
) c, w' p' I1 M; i: c8 _# S
! Y3 O% l- Z# H- p0 }1 H3 a
1 cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')
|! ?* e \* \% ~2 }% L; `$ x
2 cnxn.commit()
) U T2 m) H/ `0 G$ b9 E6 b
2 f5 v0 M* x+ |6 c% u$ x+ q. L
注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。
8 y7 D- e! T$ g4 c3 K0 g( e
( k0 V W) d1 A) g: A5 R
5、数据修改和删除
2 O7 w% Y+ \7 Q' l3 a% ^) E
3 H2 E) h9 n8 ?
1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。
1 k- K. ~/ l. {9 t" n) o+ y
1 cursor.execute("delete from products where id <> ?", 'pyodbc')
: q" t- D! M5 u0 `8 q5 v
2 print cursor.rowcount, 'products deleted'
5 n) C) _. n/ Q& v1 u4 u) p
3 cnxn.commit()
: ~+ Q( b- W' j& T3 l
2 x# H: H3 F: o6 s
2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)
( ]/ K( D, n6 g$ ^6 t/ w' ^
1 deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
$ E: D0 o0 ~* a: Y) L+ @+ |
2 cnxn.commit()
" Y, t) q7 H8 P* R9 o j( I6 x
0 s* V, ^% W$ T0 S2 L3 j @
同样要注意调用cnxn.commit()函数
! G$ z5 M' l# v3 I9 U
# R; S- p' f* v- w1 v/ D
6、小窍门
3 u* W7 |! ]7 S m& c4 n4 ^
% P8 v6 V; q) K. G' r
1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:
% z" ^( Z) H6 Y% d$ u$ v# }
1 deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
5 j- p Q$ Y8 b
1 c# ]- D' M, L
2)假如你使用的是三引号,那么你也可以这样使用:
% K! N9 f" b8 h5 u, h* ?/ ]
1 deleted = cursor.execute("""
3 k7 J8 e7 I2 m
2 delete
9 p4 G/ D0 d3 R6 @2 g
3 from products
[; j* [5 B2 T- e
4 where id <> 'pyodbc'
3 j8 W3 Y: W5 g5 A- u
5 """).rowcount
0 @3 i- L A1 U% V
- b) m1 |& G: G& j h# w, M) I$ K
3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)
8 G4 r; \1 n/ J7 D! i
1 row = cursor.execute("select count(*) as user_count from users").fetchone()
7 |( V: @ J7 [3 y& ?
2 print '%s users' % row.user_count
+ L' z O% H& Y
7 t/ I3 X! c4 g. d' u$ F! x
4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。
4 J3 b5 j( `3 u( E
1 count = cursor.execute("select count(*) from users").fetchone()[0]
$ p; {2 T$ |' |6 ]/ q+ J
2 print '%s users' % count
# D- X, {$ ^7 x
6 B( X- J) d% _7 U8 v6 L' j" S- H
如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。
, H4 ?7 F& W/ P2 \0 M. ~. n+ A
1 maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]
( [' v9 V! I7 n2 o
6 v5 n F0 f2 _; c, @- b
在这个例子里面,如果max(id)返回NULL,coalesce(max(id),0)将导致查询的值为0。
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5