数学建模社区-数学中国

标题: pyodbc的简单使用 [打印本页]

作者: Seawind2012    时间: 2012-7-4 14:30
标题: pyodbc的简单使用
1、连接数据库
9 Q3 ]9 t( y7 d/ u7 F2 D
. r1 m! Q2 L. K5 P; U6 T1 Y) o1)直接连接数据库和创建一个游标(cursor)
/ ^: b6 [' h4 [$ f3 r9 g1        cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=meWD=pass')
; a& s/ f! r7 e0 \7 r( j2        cursor = cnxn.cursor()
4 c3 Q7 S: p4 L* [+ v6 Y1 d4 r4 I2 x7 n9 H! N& e5 t0 I
2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。8 R% _* @1 r/ u( a3 |+ L8 W* \( H
1        cnxn = pyodbc.connect('DSN=testWD=password')
& \" b( T" O% _9 {2        cursor = cnxn.cursor()' J5 U; E# K; m8 Q2 ~: U

& G9 a# l5 v/ w+ N& m+ N关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节
6 r" @1 C' s& m; e9 N; [' R5 ~
* d* Y  u  Y6 |; G* q) J$ o5 Q2、数据查询(SQL语句为 select ...from..where)
( c# h0 v5 S' [. p& G+ \5 o7 y
* S- N8 W0 M3 S4 V8 |/ x7 s1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。
. K8 J' G2 ]! e  S3 r2 W8 a# V0 }1        cursor.execute("select user_id, user_name from users")
5 N3 x: y( S6 z3 n& r/ b* P) V2        row = cursor.fetchone()
0 U. d' X. M3 _1 H0 D: t3        if row:# N8 j( |: L1 V. H6 G2 C) y5 a8 G
4            print row
- z9 R$ G9 C; A9 \- K' n+ L; H
* W: P0 H, Q1 c" |4 P2 R" C1 B; k, D2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。
* H+ V+ [' S* u" B2 _5 O5 a1        cursor.execute("select user_id, user_name from users")9 E: }8 G3 S2 A3 c& y, r
2        row = cursor.fetchone()
) m# b7 v) N) T4 N5 D% p  `3        print 'name:', row[1]          # access by column index4 n( w2 f' y( \6 V3 N
4        print 'name:', row.user_name   # or access by name: ]. N4 ~7 c; D4 }: D+ w5 {3 l
& q8 x. r9 I# d+ G4 O. U, m" e7 Z' \
3)如果所有的行都被检索完,那么fetchone将返回None.- x( s6 L; e4 s' s' w7 g+ B. ?
1        while 1:0 Z% B0 H$ q6 C1 k# P2 n
2            row = cursor.fetchone()
5 A; X, G3 c( c+ m* C6 E3 h3            if not row:6 Y# o7 [. p) o% R# O  I
4                break
; U" h7 @/ _/ X: {, F7 g! |. q5            print 'id:', row.user_id
; B6 `+ c$ Z/ f- F. S- K1 M% F5 y% ?2 q3 P" k
4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)% Q, g! }/ B8 ^! a1 C
1        cursor.execute("select user_id, user_name from users")
; }- Z8 u/ k! D, _# J* G2        rows = cursor.fetchall()
1 j, O2 p3 S  e0 j3        for row in rows:
, z; {: ], i6 C+ K, h2 j" I4            print row.user_id, row.user_name
8 l2 [" j' m! [  P. N
3 O/ D& G5 q2 y: u& v$ Q5 X; F- F5)如果你打算一次读完所有数据,那么你可以使用cursor本身。
9 d2 H4 q( Y" t7 s3 X: p1        cursor.execute("select user_id, user_name from users"):& U6 U: o) A- m% g$ v7 I" o0 l. e" ^, a3 a
2        for row in cursor:; m7 }% \* f1 f/ H$ j$ Q8 y6 n9 ]
3            print row.user_id, row.user_name
! Q/ N" C( E' b6 v  z# y' n7 P' [1 S3 x+ c" [
6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:: g' [7 g. g: Q0 j& W# ^: ]
1        for row in cursor.execute("select user_id, user_name from users"):
, w+ ?; Y% e& z; ?+ L2            print row.user_id, row.user_name: q( X1 w& K! u  O3 p
( Y1 Q6 @* S+ A% s
7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:
# z# c! l6 Q6 y2 A( Z$ A1        cursor.execute("""- H# h4 z4 K# L/ s# k4 F
2                       select user_id, user_name
; K2 Q3 i/ }( G! u6 L9 N3                         from users
- m6 a+ Y: y5 F4 [5 K6 X4                        where last_logon < '2001-01-01'
; Q* O- [3 q+ {1 }/ U. B7 ~: y5                          and bill_overdue = 'y'& J  e7 l  W: u2 S# X  [- h! z
6                       """)
7 x+ k# v0 p! E+ W5 L3 L% c5 Q* W6 t" u- G# @8 o
3、参数! S5 W" u) ~) |7 d( {

+ |) ]& @' a! s0 F& X+ k2 V+ g1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。
$ e2 E. }% j  a5 Z& ~1 a+ X: x1        cursor.execute("""
7 L2 x5 A" y8 A( u2                       select user_id, user_name
/ @4 n  R1 @3 l; T& V1 y7 L/ ^2 y3                         from users! \, O& A, M( n
4                        where last_logon < ?- i: R5 Q1 ?$ O' N( x* ~- b
5                          and bill_overdue = ?6 y0 u, c3 @4 J( p
6                       """, '2001-01-01', 'y')
  S3 Q- Q$ m5 G; _9 m2 n! U0 v; e& E3 r8 f: L, o4 t# V
这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。4 a9 n0 g6 ?0 j. A* w4 @' ~# l
: }- Y( n- m6 G2 M4 {
3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:
" x# v+ t. T4 V1        cursor.execute("""
0 v, s+ e3 U  T8 A2                       select user_id, user_name
8 L/ Z2 ^, }, M3                         from users
1 W. {$ I% G2 _- F: B4 S4                        where last_logon < ?
% c: m1 W; d8 k; I6 W. p! ?5                          and bill_overdue = ?
7 C! H4 v! m4 V/ Q) T6                       """, ['2001-01-01', 'y'])
! P3 N+ P" d* Q8 w3 @
8 _0 A$ H  T( O4 m3 g! {. _1        cursor.execute("select count(*) as user_count from users where age > ?", 21)
# B* G2 K( |2 |% m, a- K& e- P2        row = cursor.fetchone()
$ L3 w/ e% \; _! z1 d0 C* h+ x3        print '%d users' % row.user_count, l3 c: a0 `  {; v8 {; C

: D6 [# u, N  |4 ^/ h  g
: y! W; l' U8 r9 P: `- ]' ^# g( |5 d+ L. f
4、数据插入
9 P& p& H% W. Z" n6 T, Z- R$ O
( Y& g. u8 K) t2 x) v  l1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。
" c( P/ T% ]% ~# C8 F1        cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")$ m  i  X2 u% s9 l+ J2 j5 u
2        cnxn.commit()" C6 d* l+ I! t6 d' |9 q0 N
( q; s5 T5 A$ P  U0 ~
1        cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')
0 L. e1 n2 g* ~& t; G0 |3 G2        cnxn.commit()
4 v) j: r1 d/ \2 H% M5 t9 F- \" V6 U
注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。
, ?0 d: B) U" b$ a# Z  @
; m- O+ V" c9 O4 z6 N5 s; V5、数据修改和删除. v4 ~2 C. e. }' f% n, h0 _

8 q( E; i6 A$ y5 F% C+ `1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。4 c( Z4 r7 Y" r" [) c
1        cursor.execute("delete from products where id <> ?", 'pyodbc')4 d! T/ r" l5 d9 c6 j% _; U8 _" D! ~
2        print cursor.rowcount, 'products deleted'' |) ~' w  y: b. @  n" r: S" @
3        cnxn.commit()4 h3 m  J! a6 c6 o; ?
4 y: }4 G" U$ [/ x: h
2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)
- ?5 Y8 s! _2 l* r1 q6 }1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount0 U2 C/ ?( ~  G6 S+ {, d
2        cnxn.commit()
2 p7 L2 \( d2 n# j, R
1 z1 Z2 A! `, v9 e同样要注意调用cnxn.commit()函数2 W( ]3 M4 Z( R, F% r  R2 V

2 a3 V1 o5 w% F/ W- M6、小窍门) G2 N% I" H! I( j5 V) v

) r$ c3 j' I4 f9 w1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:# `; I/ K" }7 G
1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount. J6 u2 S! M2 h; r; c9 y5 u& V
. H. m3 {/ _% P
2)假如你使用的是三引号,那么你也可以这样使用:
+ I6 ?0 D1 `. q7 G1        deleted = cursor.execute("""% v; Z' m* A$ W5 x$ Q
2                                 delete
' T8 R. _* r- m3 b( I9 ~. t3                                   from products
1 E5 p3 c  ]' K4                                  where id <> 'pyodbc') q$ J. [$ y" K, H' I
5                                 """).rowcount* t. A" c3 Z! I$ E! N

6 h( a7 u4 V7 ?; G5 O' n8 e; ]3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)" c7 R/ k1 l/ ]( n4 t* ~& |
1        row = cursor.execute("select count(*) as user_count from users").fetchone()
# x0 X' B7 w& X/ ?2        print '%s users' % row.user_count! W. y& f( H& a1 o( P

  X8 Q0 I2 }$ h4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。% r2 J5 F" c/ `0 }1 a1 S; Y# w  D* n
1        count = cursor.execute("select count(*) from users").fetchone()[0]
! F/ P) c8 x7 Z* q$ W2        print '%s users' % count
$ S! x8 f4 u3 I" b, J) B# {' B9 a6 `) f! }9 O3 B6 O' [& g
如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。
1 @% z) u$ k, f5 ?5 N, ?, l$ b7 l1        maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]
1 a. ]7 v7 M+ ?* a/ ~, t8 d
: @9 I! r3 T+ r$ ~# x) G在这个例子里面,如果max(id)返回NULL,coalesce(max(id),0)将导致查询的值为0。




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5