数学建模社区-数学中国
标题:
pyodbc的简单使用
[打印本页]
作者:
Seawind2012
时间:
2012-7-4 14:30
标题:
pyodbc的简单使用
1、连接数据库
9 U4 u( F: k/ J) G: p7 Y
9 g( x$ v* @4 f: O
1)直接连接数据库和创建一个游标(cursor)
& v1 q }; a- \9 y! Z
1 cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=me
WD=pass')
+ F( p6 ~- Q2 q- Y4 {& s
2 cursor = cnxn.cursor()
" s9 _7 T& O( o: }( u) n! T
[. H2 R0 k1 }; u: B! H. W! c( e
2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。
) U7 b* p- H1 P$ C2 ^4 i
1 cnxn = pyodbc.connect('DSN=test
WD=password')
, ]/ M( C: W8 ]% N! M" u. Q
2 cursor = cnxn.cursor()
. X. `' Z% [4 m: U0 h( q
) p- }' i' }* Q4 C& f, m% c
关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节
7 l* y; l M7 w& K( b9 U/ T
; k: |# l; g0 h/ e/ u3 p) J! w
2、数据查询(SQL语句为 select ...from..where)
. h0 ^1 q" M& p& M' Q; g
: e# G$ A1 N/ |: L& E% U/ w
1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。
% V3 \9 c! w4 O8 o* W( W3 l
1 cursor.execute("select user_id, user_name from users")
- d2 ]/ n! |' I- j, `7 [
2 row = cursor.fetchone()
2 b" S p3 L( X) ]; u4 S
3 if row:
/ \, Q0 Z; c2 i6 x0 O0 D0 _/ V8 B3 s
4 print row
2 M* }- j! O" A7 W% ?6 U% d
* ^7 q7 A' W R
2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。
. u' _% g2 j, [
1 cursor.execute("select user_id, user_name from users")
! {, K0 U! h- g# q( k% ?
2 row = cursor.fetchone()
( R/ _: b- t3 t- t/ r
3 print 'name:', row[1] # access by column index
) P3 y# l1 \* i! b4 o8 L
4 print 'name:', row.user_name # or access by name
3 p, v5 |6 j, A% M/ ]/ b: q
" S, w# G$ H" H/ e4 e: p
3)如果所有的行都被检索完,那么fetchone将返回None.
, ^* o. n" _. S6 z! f9 G; Y. ?
1 while 1:
, c c( @! Y4 b( [( `6 O
2 row = cursor.fetchone()
+ N) F, @* b# I0 J
3 if not row:
2 Y+ x0 G+ B* R( ]+ ^" i$ h/ H
4 break
5 P' {* j, m( } R$ O
5 print 'id:', row.user_id
7 i! \$ ]0 y" S; P3 U& J
! b1 C: a( K" _3 N" J+ p' d
4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)
* K6 }, N: B: ?+ _5 {& i% ]
1 cursor.execute("select user_id, user_name from users")
+ o8 q" q- O/ [; }
2 rows = cursor.fetchall()
& O, O v9 G- O( N' T
3 for row in rows:
/ V( M" [3 p& i
4 print row.user_id, row.user_name
+ k' J, b6 A) V. h
% _! W* d7 X5 j+ o2 M+ v* N
5)如果你打算一次读完所有数据,那么你可以使用cursor本身。
' _$ ^8 @4 S n2 \8 h1 ], y' O0 @
1 cursor.execute("select user_id, user_name from users"):
/ k! z: o) E6 N
2 for row in cursor:
+ {$ u( y( [$ b3 ^' K6 `* d% `
3 print row.user_id, row.user_name
" v! W3 @+ u+ ~1 ~( u# S
7 A1 P5 ^" T* v
6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:
" N8 h' n2 Y# h0 r3 U
1 for row in cursor.execute("select user_id, user_name from users"):
# n7 |8 C& a! p; Z! v
2 print row.user_id, row.user_name
d& n$ v6 Y W
. q( I4 Z6 X/ T+ L& c9 T
7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:
; Y; y* v. D0 s6 A- f; R4 ^# {
1 cursor.execute("""
9 G) o2 ]* T) {+ {$ v2 _
2 select user_id, user_name
5 H6 F3 @1 e7 f% }; X
3 from users
) ]' O5 j% m# ~+ \# @. ?4 f+ f
4 where last_logon < '2001-01-01'
/ n+ ?1 Y. M" v& m7 D9 e& m, x5 b- d' Y
5 and bill_overdue = 'y'
" ]; l. J6 X5 [8 L; t; M% I( M: f
6 """)
. P: L) q2 v/ K3 i/ p
/ Q- t6 p9 a6 y( D3 W% r
3、参数
# p* M# V# d; H$ W6 S, m
7 P# H& O- w# h+ @, E% M, g! v
1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。
9 R S- `0 B# Q/ r/ D, `% I
1 cursor.execute("""
; e8 S$ Z1 r/ ]0 F& j# C
2 select user_id, user_name
, O6 @& B$ F2 R0 c
3 from users
8 s) H6 m7 {& v; h; A; v: C
4 where last_logon < ?
( z, S6 w9 ~* g5 y" F
5 and bill_overdue = ?
) e0 b4 p+ Y( h; b
6 """, '2001-01-01', 'y')
6 r& k6 y4 l& P
* v, T) f, O+ G; j" C( Y5 n X
这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。
" G/ | v) y) ]* N
: O4 l) l4 p$ I
3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:
, c8 L6 ]* F) u2 L' }1 I; V$ f
1 cursor.execute("""
' ^# R- Q, R; H" D8 Y% }4 B& n; H
2 select user_id, user_name
) ~- Z k0 M7 w, w4 B' W
3 from users
0 C4 O4 l8 f) \" F2 g; B1 p
4 where last_logon < ?
3 k7 G/ o- M/ b5 M. N" x
5 and bill_overdue = ?
| o) F! a# [& j" x
6 """, ['2001-01-01', 'y'])
$ b/ {1 G' Q# i* u8 ?* g. S, E
. m$ n8 w+ a: b7 v$ v
1 cursor.execute("select count(*) as user_count from users where age > ?", 21)
( P; M! X- S+ N! T
2 row = cursor.fetchone()
* R( k$ P8 T( C' e: n' g
3 print '%d users' % row.user_count
7 \% ]" `/ D0 O' N6 {
& X9 z2 |' \: E8 w' ?
7 I0 h8 y/ G! Y9 M4 t* b _5 `
3 U9 E( L7 ^& W) w# V" b# q
4、数据插入
- k9 {& d8 J4 ~; m" C
F# `9 f- h1 H! ?" O$ `" r9 l
1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。
- t& ~0 Z8 X$ o
1 cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")
* S2 x; a! g' _3 ~1 y
2 cnxn.commit()
5 J0 j5 ?+ B6 \7 [' h
5 u# v' C- o+ R k% K
1 cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')
! F( ^( p6 r+ @8 _- e5 S* s
2 cnxn.commit()
$ k6 Y1 J/ b! e. z; ?3 b# s7 L
7 d6 M& @8 M8 P6 |! |
注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。
/ \1 ~2 f' R7 w# e8 Z" I. f" |- O
( w: t% ~6 a% @( V; Y+ E* n5 E5 i
5、数据修改和删除
. a8 X* s: V1 v+ h1 h [
: A% I- k- m# I. @
1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。
) x' P3 J4 p8 Q0 Q$ z0 n8 Z% K/ x
1 cursor.execute("delete from products where id <> ?", 'pyodbc')
+ d2 W- s8 o! p
2 print cursor.rowcount, 'products deleted'
* ]0 o" `; j3 [' ~
3 cnxn.commit()
& A) w4 _3 K/ A; E) ?
8 s p2 g7 g5 Y
2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)
0 _( z/ a# D. X4 `8 A T$ B) c
1 deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
) B" P5 K I8 s1 K9 K7 m8 j
2 cnxn.commit()
% w3 \* v. [& |
! `1 X/ y( @* V U& a0 V
同样要注意调用cnxn.commit()函数
7 W6 }" h2 E! W3 \
8 `" r5 a5 S0 x8 r
6、小窍门
) r2 S" k! f ^' ]
8 k$ C/ J' O' V# {
1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:
" a3 j d+ E( j: [" J
1 deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
& e. n- i2 B! D/ p
; ?+ `$ \1 C9 _3 E6 t# }
2)假如你使用的是三引号,那么你也可以这样使用:
s: v4 y7 E( k- F3 `; ?5 L
1 deleted = cursor.execute("""
, r3 A7 f2 Z9 k6 u. w, d
2 delete
9 o4 {) l# y, V: h7 @' h
3 from products
2 i# Y7 ?4 J( S: ~8 D# q
4 where id <> 'pyodbc'
$ K1 J& s) @) V, g$ @( \9 m1 ^. I
5 """).rowcount
4 g* C: v$ }7 G7 R! M; Y6 F) Z7 S
, ?4 \, j4 g) S0 V4 {
3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)
6 W2 ]: Z* Z3 h% | k6 J0 V7 l h
1 row = cursor.execute("select count(*) as user_count from users").fetchone()
/ { I {6 y. M
2 print '%s users' % row.user_count
1 S0 j" F+ t9 i: Y! z
8 _" E8 E. E# u
4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。
* _( e% p8 Z7 S$ _) [
1 count = cursor.execute("select count(*) from users").fetchone()[0]
0 K9 q* H% ]3 f6 W4 R
2 print '%s users' % count
8 `$ |; m4 G9 ~' w. O. |+ t7 E
1 P; C; U# k" Y7 K/ y
如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。
& [0 j+ O5 G# r
1 maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]
" `) J# \2 Y+ ~1 c" O
8 v; J# i5 M# t. ~- g( o( W
在这个例子里面,如果max(id)返回NULL,coalesce(max(id),0)将导致查询的值为0。
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5