QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 6146|回复: 0
打印 上一主题 下一主题

pyodbc的简单使用

[复制链接]
字体大小: 正常 放大

102

主题

5

听众

913

积分

升级  78.25%

  • TA的每日心情
    开心
    2013-4-28 12:11
  • 签到天数: 160 天

    [LV.7]常住居民III

    群组数学软件学习

    跳转到指定楼层
    1#
    发表于 2012-7-4 14:30 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    1、连接数据库
    6 [, o, l0 o9 J4 ?( b! Y
    ( ^& w% l/ Q: |! f1)直接连接数据库和创建一个游标(cursor)4 D* J2 O6 _/ S
    1        cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=meWD=pass')
    * A$ x$ {! V! x+ U) o; }- Q2        cursor = cnxn.cursor()
    4 I! h) X8 F% Q) [; c# Q4 m" V6 M7 F+ t! ?8 i+ k
    2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。
    2 ?% }" A" V' c1 _1 e# c1        cnxn = pyodbc.connect('DSN=testWD=password')
    6 s+ @  k$ G1 }! h! l2        cursor = cnxn.cursor()
    5 t! [/ g1 q, }" c, w! Q+ \
    # U0 U5 z1 a* H: M关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节
    ) _8 h3 l( W3 d/ _  f- w  G+ o; ?( c! |$ d
    2、数据查询(SQL语句为 select ...from..where)
    6 f" U+ X4 x9 |2 F: W" a( Y5 f6 ^" \9 U9 b# V5 p
    1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。9 G2 E# `* q: S$ ?; b6 ~% z
    1        cursor.execute("select user_id, user_name from users"): N( F0 Y/ w  o
    2        row = cursor.fetchone()
    - R4 @% K  z6 d* j1 ?( L3        if row:5 o5 N0 E0 Y: y
    4            print row/ }3 @9 [/ N) s! P5 s
    4 {( {  i2 @! j) b  O. ^  x  w
    2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。
    0 ^( `! X5 z$ z" W3 Q1        cursor.execute("select user_id, user_name from users")# e3 R; V, w/ G6 f6 w3 |' D$ Y
    2        row = cursor.fetchone()! D0 O# H5 q' n! o2 K
    3        print 'name:', row[1]          # access by column index* a# `4 ]% |9 Z  b+ \
    4        print 'name:', row.user_name   # or access by name" N: W1 p& {" Z/ `, T# N

    / R) o/ r# \* ~3)如果所有的行都被检索完,那么fetchone将返回None.( C" ]! X$ m1 ^: m$ N+ A
    1        while 1:
    9 N( `6 `; `* s+ H0 t; e8 g6 u9 I0 V2            row = cursor.fetchone()
    ' a7 w& `& Q7 n- b* m3 B3            if not row:
    / p% n; g# w2 H- R1 |: _2 W/ f+ A6 L4                break
    0 e$ A* P5 }0 E1 Z5            print 'id:', row.user_id' K' W1 q3 z+ _6 a6 W- |
    $ g  y8 K& v# b: B4 [
    4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)1 p; O* d/ _/ d/ D& Q
    1        cursor.execute("select user_id, user_name from users")$ V: B/ K8 w4 [* m6 L
    2        rows = cursor.fetchall()
    ; d5 b( u6 x% `8 f' ]3        for row in rows:9 o* i7 N3 e: F5 x8 j7 b
    4            print row.user_id, row.user_name
    7 @. U2 C- ^$ k4 S6 v' s6 T% X2 l* D5 u
    5)如果你打算一次读完所有数据,那么你可以使用cursor本身。2 |1 f8 h: g* @3 g" T; m
    1        cursor.execute("select user_id, user_name from users"):
    % H  X7 l7 e# D7 D2        for row in cursor:# j* v( }1 w( R8 L
    3            print row.user_id, row.user_name
    ) ^* _, {& e2 r; D1 D) I; l4 {+ H
    6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:: _, B8 E2 Y$ i
    1        for row in cursor.execute("select user_id, user_name from users"):- O* a* z* m. x' o5 a: ]
    2            print row.user_id, row.user_name
    ; \7 M+ b7 G6 m0 [
    % b+ n1 i8 J+ n3 q1 K" U1 N7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:
      U* V; o/ V% l/ x7 q1        cursor.execute("""
    ( D9 N. `& M6 n) q" @& b" b6 N7 _2                       select user_id, user_name% x4 Y' T, v% E6 n9 e4 I
    3                         from users! G; z4 n) G2 |& ~" ^* m
    4                        where last_logon < '2001-01-01', F" R0 \* E1 s( C
    5                          and bill_overdue = 'y'8 N* P7 U3 Z/ s% s- i% J
    6                       """)
    * {! l3 K* F: d1 b
    # h5 P' x- E* [# E* `3、参数- o1 b& s. K+ y1 m6 ~# g( B' s
    6 v: \) w6 q7 g8 L& K, ~% q) q' K1 z
    1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。
    9 D3 H* v0 l9 D- q+ \! I* l1        cursor.execute("""
    & q  O7 l2 D0 m! X+ E- p2                       select user_id, user_name$ x) ^6 A/ Y" v
    3                         from users- d, j8 E$ u- |$ l+ H# s
    4                        where last_logon < ?
    3 ]" R& Y1 P# q7 V$ S7 V) `5                          and bill_overdue = ?
    + F) E9 Y! \2 c/ ?( G6                       """, '2001-01-01', 'y')
    7 D. P$ H8 D- I  z& x- ?; e1 D; u. P& R# k( v. p. ]
    这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。
    & f4 A  ?2 L- z5 u# P! N* H# u9 G6 V6 N2 R5 C2 Y- I- w1 T
    3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:
    1 I" Z# ~# \6 u0 Y* S+ B# ]1        cursor.execute("""
    . `6 X& M& c: K. k3 \2                       select user_id, user_name) m* l% j' J3 H# g: H
    3                         from users
    ) k' ?2 _# q3 @+ c' S' u4                        where last_logon < ?
    3 O" ]% K: \- q% W* \# x5                          and bill_overdue = ?
      x" W: h* d: O$ q$ w! q( B6                       """, ['2001-01-01', 'y'])
    1 q# Q$ [" j3 ~* J2 T+ N) F2 S* f6 K/ ~( }! {
    1        cursor.execute("select count(*) as user_count from users where age > ?", 21)
    # i2 g; j- v. _- F7 g7 d2        row = cursor.fetchone()
    9 Z& x( v6 O# M  ]3        print '%d users' % row.user_count3 P& _" M2 l% i/ {% ~- `
      s0 U! |" M- F; K8 S

    # X# K! r) k8 r" W9 r2 G4 e4 s  A- w( P- h- B
    4、数据插入
    3 z% r; M4 Q: D' A: \* H  b8 g
    . Z% ?5 R3 \5 F& n1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。
    9 g4 F2 T/ ^- f- x4 P1        cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")
    , ^: `- y" g5 P( i: U9 Z5 W. \2        cnxn.commit()# J0 n/ I; \# S2 b
    & R& E6 ?8 z8 _. T+ A# q
    1        cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')5 ?, m, F8 J( X% A
    2        cnxn.commit()
    1 Y+ q! n4 A, X$ W( V. i8 X( T0 J4 L0 z" i" U" n1 }
    注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。
    : ^1 h- v% c- p4 h: I7 r+ d# h7 f$ t( d3 M6 c
    5、数据修改和删除9 K- D, A, s# z) d

    3 }1 z. C/ K/ O, V& t% e/ z; N1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。
    8 G7 p9 t2 n# j! K! S$ z9 k* U1        cursor.execute("delete from products where id <> ?", 'pyodbc')
      y; U: _5 x/ G( \# S; F/ Q2        print cursor.rowcount, 'products deleted'* ?. g# A! z0 m2 b0 D
    3        cnxn.commit()) G. J7 u! `" a. X* @" v5 K: V7 J

    . l3 q% }! O1 [0 n% X- L2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)2 n- f; |2 h! b! l, {7 X0 G' \0 c8 n6 K
    1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
    3 C- s3 {+ R, m* H6 s: V/ E2        cnxn.commit()
    : L1 B3 n) F" H4 \9 y9 E
    - r. a" T  |& w4 {, A' [同样要注意调用cnxn.commit()函数, |5 o1 U( K) r. O% _/ y
    0 e* f: p* D! s
    6、小窍门
    2 I+ B6 o# I* t' x9 `2 u; m- [9 l0 x: h+ F# y
    1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:, r1 U! D. F9 v, K$ Z
    1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
      Z5 X" ^+ J* r% D  U- F, b- M! ?. ~/ t# o
    2)假如你使用的是三引号,那么你也可以这样使用:+ Z8 q6 ?4 U( d# G
    1        deleted = cursor.execute("""
    ; _8 C3 B* Z- ^, c2                                 delete5 S) K9 H$ S' M. @
    3                                   from products
    5 h$ @* f: R5 J9 \4                                  where id <> 'pyodbc'! I: D* ^6 q: ^& d; w3 u4 o9 f
    5                                 """).rowcount
    $ d7 E+ K2 m$ x9 d7 O
    8 [# I6 e/ P& X( f2 E2 k3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)
      u$ a7 {5 a1 ?( w- Q1        row = cursor.execute("select count(*) as user_count from users").fetchone()
    & o, p7 Q* k. a* G1 O5 ~2        print '%s users' % row.user_count! D- S  Y: C  N( `# _" H6 y/ t
    " c$ B* F: u$ O/ \) z+ F6 }: n! ]6 F
    4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。
    ( k5 H: F* p3 K* O/ l1        count = cursor.execute("select count(*) from users").fetchone()[0]! Y. \: |  }, ]+ s0 O4 m3 w) Q
    2        print '%s users' % count
    6 M& F5 @& E2 f  G0 O' t* q% A) D! K3 h9 N; {
    如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。! P# H. S) z6 i. L: {; p/ Q: B
    1        maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]* c; W; c) r* y7 M$ r
    4 B8 U6 b% |( }7 N6 O' |( B
    在这个例子里面,如果max(id)返回NULL,coalesce(max(id),0)将导致查询的值为0。
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    《舌尖上的中国》所呈现的不只是美食,还有文化。这种被现实挤压而仅存于小时候的记忆,让人回味的同时也唤 ...
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-6-11 18:10 , Processed in 0.425150 second(s), 50 queries .

    回顶部