QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 6086|回复: 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、连接数据库
    2 X, h% z( h  }2 {5 D1 ?
    7 c. N2 B- s# p1)直接连接数据库和创建一个游标(cursor)! F9 x5 ]! H- q8 d  w0 w, g8 z' R
    1        cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=meWD=pass')" P$ P% z( d/ ?& ^
    2        cursor = cnxn.cursor()
    ! _9 U! m7 V. ^9 {: F& d- k! M" P( f5 w# e3 z8 r% R
    2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。% J6 M( F( r$ n, f
    1        cnxn = pyodbc.connect('DSN=testWD=password'). z, y+ N5 r4 @* f8 S8 i6 y
    2        cursor = cnxn.cursor()2 q2 j1 e& M5 m  a( X
    . z. x0 r4 ?% v# u
    关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节
    # c+ y/ U5 e8 ~* i( _
    9 `* r1 H- a# _1 ?: h& ~3 G# W- ^2 a2、数据查询(SQL语句为 select ...from..where)1 N; x8 d  p# B) R9 }7 v
    6 d: M  l- f& k; J6 W; S$ d- C8 w3 `
    1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。
    - O* m3 J! U7 K. r. D- @1        cursor.execute("select user_id, user_name from users")* Q( i6 x! ?, E" u- M0 b. s  g
    2        row = cursor.fetchone()
    ; a# }* R' a" D& V' \" _3        if row:
    2 \  x4 \" K* K7 ^/ M3 L4            print row7 v6 _' |' `& X# @3 l' L- `

    ! q$ f8 v! j1 R7 x5 R/ D2 s2 q9 B2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。
    3 }% n  a  s1 @5 @4 I1        cursor.execute("select user_id, user_name from users")  ^/ g! P* p  j' B6 k
    2        row = cursor.fetchone()
    " }5 z: `) s+ P+ o* Q5 _, ~8 g3        print 'name:', row[1]          # access by column index
    & w6 S* f0 Z# t: o; p2 m" {; p. E. s4        print 'name:', row.user_name   # or access by name7 F! W- K/ {4 `2 n
    - j) b. i: _; s/ I
    3)如果所有的行都被检索完,那么fetchone将返回None.# J+ I- A, V" D7 t- N7 f: l, q
    1        while 1:& `# |* `; ]  x$ @9 L; W0 R
    2            row = cursor.fetchone()9 c! p6 Q" b  r! G
    3            if not row:
    8 n: f2 z" D! @* }4                break
    6 W. Y& q! ?9 }* y4 s5            print 'id:', row.user_id
    ' ^# W9 ~8 H- o7 G6 b5 b; B/ C" q# |; t8 g" Z& p: a# o
    4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)
    8 u2 P3 F4 X+ q# U4 A1        cursor.execute("select user_id, user_name from users")0 x, L  N# a& p
    2        rows = cursor.fetchall()
    % \: @: ^" J* s# c; k0 o3        for row in rows:
    " I4 j$ ?' u6 ?0 [: y. l8 g4            print row.user_id, row.user_name* X* S* u3 e( o0 Z, V" |
    : w  G% d+ x" M/ s# \( P. G
    5)如果你打算一次读完所有数据,那么你可以使用cursor本身。* j+ C$ T& v. F! y1 N; b, e3 M
    1        cursor.execute("select user_id, user_name from users"):
    " A5 B/ g7 V  A& g* n" v1 m7 E2        for row in cursor:8 q  _8 h3 {: W/ c0 t- ], V
    3            print row.user_id, row.user_name
    & r1 q2 O- _( V1 h6 m5 p: g
    ; C! u0 {( O# n1 q6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:
    . W4 V5 Z$ I0 ~8 @3 [( a0 s1 s& c: d1        for row in cursor.execute("select user_id, user_name from users"):
    1 K- Q6 ^$ I# T% X9 o9 r; K2            print row.user_id, row.user_name
    ! S+ Z" h# W7 V/ A
    3 i0 c! Q: [& h) ?7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:: Z; k8 I, ~8 K
    1        cursor.execute("""
    3 s) j6 G5 Q+ x3 M2 Z2                       select user_id, user_name1 D/ F8 g% ~; U" L9 `* T& K+ o
    3                         from users* {8 p, h+ _' A" X
    4                        where last_logon < '2001-01-01'
    ! C! W2 p& g& I4 \5 Z& h1 W8 \5                          and bill_overdue = 'y'
    2 |4 Y; M5 I6 N6                       """)
    3 b/ C& `" g1 T$ A. P# h# W) `0 I& S9 K( P# n# s
    3、参数8 y0 }2 v  ^. ~6 q$ x4 t

    : K( r  m4 k6 z7 v" l3 Z1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。$ e" D  n2 f* \, l
    1        cursor.execute("""3 `6 ^. [# d, F- @* |" Z
    2                       select user_id, user_name
    3 y3 P; e6 j' z4 f6 h8 v. }  W3                         from users) s" U( x' W( n9 u: @
    4                        where last_logon < ?, M8 R( |* p" O  I1 B
    5                          and bill_overdue = ?: ?6 Q: c, Y( ^+ k
    6                       """, '2001-01-01', 'y')5 h3 h9 w3 w' z  S7 ?5 a- h

    ' f8 k5 d$ K5 ?% {5 W% b$ z这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。
      H6 s' C0 v* G# H) J  B- s' [  L' o* u, [
    3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:; F7 B# G, g+ {+ L- n+ d, j# `8 u
    1        cursor.execute("""
    ( Q: c# I  s9 S: {5 {; i6 f2                       select user_id, user_name; T* Q2 F6 }3 _( v! T- R% q8 c
    3                         from users
    % {: A8 m7 w( W$ m9 i- w. M4                        where last_logon < ?& k1 j. p* Z; R. Q
    5                          and bill_overdue = ?+ H" j6 w2 N6 C' M( F. g; D# m. N4 P6 K
    6                       """, ['2001-01-01', 'y'])0 `# {" b. P+ w' H( w
    & v/ V2 x9 y- P4 K' I% R
    1        cursor.execute("select count(*) as user_count from users where age > ?", 21)% I+ l, j7 `! t( I; w+ R! g+ o
    2        row = cursor.fetchone()
    & U8 o6 [2 g% k3        print '%d users' % row.user_count1 p" @, g5 F8 J; X

    , y9 u1 _" J9 }, _) d- v ! _3 c! m3 f& R! B) ^0 D
    ; t/ ?/ _) b$ i
    4、数据插入
    6 q4 E4 X8 d/ `8 u9 b9 \+ d4 `) j, m$ c! M! E
    1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。
    1 d. f4 D0 |- p- p! t1        cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")0 g2 l, D8 n; U( [) k6 c
    2        cnxn.commit()7 R# k& {( p& p# B& F( ^/ @

    / h, l& w) Y) B1 E1        cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')% r( D, r7 `& Q/ X- [
    2        cnxn.commit()# N/ L) V( }1 N) i4 w1 b2 R) M5 m
    $ ]7 C9 l/ T2 {' ]$ Q# `; K
    注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。& ~4 o6 H7 y* q- u2 \' F
    / _3 G! @1 i8 N( ]
    5、数据修改和删除
    ) Z& z& s) g9 p( h3 a; v) q% ~* {3 [, d8 y4 v
    1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。: h" D; d; t0 S9 Y, z+ m! ]  V
    1        cursor.execute("delete from products where id <> ?", 'pyodbc')* p; e4 w# E8 U! O4 N/ O
    2        print cursor.rowcount, 'products deleted'
    ; W5 o7 B2 M( Y( {3        cnxn.commit()$ I" S7 U' B# j1 B, i
    6 R) o5 |3 C6 ^" w
    2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)
    ; T3 r8 T* V4 O2 X8 l- t$ }1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
    + |# u9 h& M. t) }8 d5 J" i2        cnxn.commit(). Y+ s5 |6 Q- Z4 O. B

    9 `9 r$ T8 p1 U/ {同样要注意调用cnxn.commit()函数- E1 \( o  O+ K

    2 y) M- i" t- c. n; v# Y9 D$ L6、小窍门4 N' s' k% ]& \0 L( m3 N

    & J- f* b0 y, o4 [! @1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:/ T! R* C9 L% S" Y. y0 }( k
    1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
    ( ]' [3 g% X3 T6 y3 o: t5 P* X$ E7 U& t
      b3 o7 T& M( O' H" H$ m2)假如你使用的是三引号,那么你也可以这样使用:
    ! r! X! B6 L9 z2 }9 K8 I$ D3 t) H# d1        deleted = cursor.execute("""' Y" u6 A' t% ?0 p, V5 @* ]) V5 E
    2                                 delete$ V& B$ Q$ g* L7 L
    3                                   from products
    " L, V3 O, G7 K. W4                                  where id <> 'pyodbc'# }6 s+ ?6 _% m
    5                                 """).rowcount; d' o! [$ O5 w2 J  i% Y0 A

    & |3 o+ l0 t/ Y3 ?" o3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)$ h- _4 y0 n0 a. n6 g& ^
    1        row = cursor.execute("select count(*) as user_count from users").fetchone()
    & _% K- \+ s: s; I, U2 P2        print '%s users' % row.user_count7 M8 g0 C0 n% t3 `) w

    - I3 x) z+ ^9 h' E" @; ~2 U4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。( S2 P8 t" L, S0 s; Z
    1        count = cursor.execute("select count(*) from users").fetchone()[0]8 _- g4 E. A( N* t$ A
    2        print '%s users' % count$ H" [- t; u, ]
    , e  D0 H2 C" V, x
    如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。" Z' p" e- @( Y* B
    1        maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]# ]" r3 o& {* v" q# b
    ; B6 H! i* l4 [2 R) A
    在这个例子里面,如果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-4-10 12:00 , Processed in 0.375063 second(s), 49 queries .

    回顶部