QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 6154|回复: 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、连接数据库; a2 R) ?( h/ C' U$ k) w/ O

    & w; t9 a+ v$ I9 N3 n1 Q5 O5 B+ w, k1)直接连接数据库和创建一个游标(cursor): F0 \* a) n) i& D% y1 z
    1        cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=meWD=pass')
    8 F7 V; I* b+ s; w) ]* w. L( {& }2        cursor = cnxn.cursor()
    + g- {9 w) s% M; m# x, e
      ~$ p  r. x" Z% o- d2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。
    0 @8 v- d9 H, @4 `& e1        cnxn = pyodbc.connect('DSN=testWD=password')
    " [) o  K6 g% I7 v  V2        cursor = cnxn.cursor()
    - Z: B/ O- M0 E1 L: O
    " |5 |" x& B4 E' {1 F( H关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节
    4 o$ T' [5 L! z2 m2 q+ N* V! V
    5 |% X+ F6 b( Y$ H2、数据查询(SQL语句为 select ...from..where)
    4 Y% e! N3 A% _, r. l: G8 K. R! d9 r2 P$ O# v  ~
    1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。
    $ `. \+ @- \+ M1        cursor.execute("select user_id, user_name from users")1 s# _% n6 r' }3 j  W6 p5 _
    2        row = cursor.fetchone()0 y" N/ I# y1 `8 i
    3        if row:- i8 b3 o" O! @! c
    4            print row; D+ o; \2 M! q0 c) A  `) @

    ! p0 E0 x* m4 @, [3 e* t% t2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。
    % f* ^7 C4 c8 ]- q+ y( L2 E7 k1        cursor.execute("select user_id, user_name from users")
    6 t3 `$ }; r+ g1 K2        row = cursor.fetchone()
    5 G$ Y0 z8 ^. a+ v' h. |) [) x* N3        print 'name:', row[1]          # access by column index
      d- P9 n5 A+ c. e9 J# V& Y4        print 'name:', row.user_name   # or access by name# O$ M% z- Y$ N; w7 x1 g& d

    % V  t- L# A: k3 M% N/ R# E; d3)如果所有的行都被检索完,那么fetchone将返回None.
    - Y5 p6 a8 m. J1        while 1:
    8 s1 A& y: B) v+ u6 y2            row = cursor.fetchone()
    9 ?/ X5 }# l2 C7 O, W3            if not row:
    + O& _/ Q/ h. X/ }$ {4                break# }/ {9 p% \1 V- `
    5            print 'id:', row.user_id- a, u9 I9 Z  L. f  s! W
    * _4 H5 O! I3 ^$ I! _; F
    4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)
    ( U/ K7 P- I* v( U1 s1 C1        cursor.execute("select user_id, user_name from users")# E2 m- ^( g- Y. `4 p
    2        rows = cursor.fetchall()$ V3 ~8 X8 Y+ r5 h8 I
    3        for row in rows:
    ' H' j1 h1 y  T( k4            print row.user_id, row.user_name+ ]- z. Z4 ~3 q6 Y6 w
    / R. z& B6 w3 T2 a" d# I
    5)如果你打算一次读完所有数据,那么你可以使用cursor本身。8 x! p) I4 x: o! A1 S! y
    1        cursor.execute("select user_id, user_name from users"):% Y1 K1 |* ]1 l# ?  s( V
    2        for row in cursor:4 n" S" O% Z9 Z
    3            print row.user_id, row.user_name
    ; H2 ?! k  G! V- `
    . h: L& a5 W: d, a3 d/ M6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:9 ?- ?5 u8 C! f- ^  A' [
    1        for row in cursor.execute("select user_id, user_name from users"):
    ; h# \# T5 F8 L4 m2            print row.user_id, row.user_name# s* r* n4 N7 U  c9 d- D

    * C1 \+ |7 g. j& u2 j3 J7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:3 W6 h: l) v* e1 Q6 D
    1        cursor.execute("""
    ' ~( ]  ~& h$ {- s7 M2                       select user_id, user_name
    + c% W/ W; t* N* {, E- J3                         from users, k* I1 l4 k3 C3 H
    4                        where last_logon < '2001-01-01'
    8 {, k1 V, R  W. A/ d5                          and bill_overdue = 'y') c9 B7 b5 a* b( Z( w
    6                       """)
      P1 c. d3 _; @; G! J5 {4 ]; V' ^) m* w0 r
    3、参数8 R! y2 @0 x! W5 X1 g2 K' b
    * a. p$ F  J1 M- T- b2 w: _0 B, t2 ~
    1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。
    2 Y6 k" G, G$ b' l  w5 ?1        cursor.execute("""  d- E+ w1 W3 D$ @: J7 n
    2                       select user_id, user_name. x4 ]$ w  P5 z3 {1 v
    3                         from users
    . l' u- k" n' r6 ~: n4                        where last_logon < ?( j& z# O2 I! \
    5                          and bill_overdue = ?
    ' c, Q4 F8 J8 A/ c0 T) [! A( X8 \- [6                       """, '2001-01-01', 'y')5 J  i, i* R7 Y" B6 a

    . v$ E/ I9 V/ u这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。! q; b- H: U/ [/ c; @! ?

    : x- V, y/ n; k3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:+ T3 I6 F$ @, I9 A
    1        cursor.execute("""" L& v. B  t; B0 a
    2                       select user_id, user_name7 L+ I' B; R( A7 }7 X" Y3 ?
    3                         from users
    * K+ A7 t( J' N8 I7 F7 z  f4                        where last_logon < ?$ U- c3 l+ ]# e1 r+ u- D- `
    5                          and bill_overdue = ?
    . Y- x- _- z4 o; ~- a: X6                       """, ['2001-01-01', 'y'])5 o& a; m2 r' _0 j
    * F8 G3 I0 Z3 n1 w& v
    1        cursor.execute("select count(*) as user_count from users where age > ?", 21)
    ( o3 h3 W  e/ X1 D' E. _/ ~) x1 P- [2        row = cursor.fetchone(), B+ `. ?5 Z4 V/ b- c# F2 p
    3        print '%d users' % row.user_count
    + D% [. d2 L9 U/ ?4 f1 P8 U6 x3 d# c3 H5 x/ v4 j
    3 T: B! t( E( I  C; L+ b1 F
    - M1 |1 W! R6 ?/ g, ?# w9 a
    4、数据插入- q7 `3 T" F5 w, ^. I* l/ T
    ' P/ v9 [7 V' y+ e! N
    1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。+ T4 `8 ~+ U0 b) s4 s
    1        cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")9 I7 ^6 E) t, e7 X
    2        cnxn.commit()- `8 X8 [4 w$ r6 \0 F

    3 N" J4 I! E' F6 E4 I( {1        cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')2 ]( K1 e% u/ z
    2        cnxn.commit()# Q! l; {, D! T! x4 x1 J) N

    4 L' z" s- ?- U2 y" z注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。6 i" f  n# N9 u

    . [2 N( a& P: C" W% }5、数据修改和删除
    # }6 q! x2 x7 S8 A6 I  ]0 X8 m5 p3 ~2 `) L7 E' Z' f
    1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。
    ; r  u( ?4 t2 z8 p6 a* v1        cursor.execute("delete from products where id <> ?", 'pyodbc')
    * N0 P. s3 z2 i- C/ @! X2        print cursor.rowcount, 'products deleted'  j, s0 L9 B6 v2 _3 V$ y4 [5 u( T
    3        cnxn.commit()
    : |4 O  w/ M/ i0 P9 K' Y; }4 a3 @7 z! ~7 n0 T# }% h
    2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)! L2 G# F. k8 e+ b# |! m# O& N+ ]
    1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
    8 A. O1 d% o  l) U/ g2        cnxn.commit()3 P7 K& U; f2 e" H7 G' {* z

    . A9 A& w8 V( R同样要注意调用cnxn.commit()函数
    ( m! F6 u) B) c2 r4 Y4 B  J0 P4 g0 r+ V
    6、小窍门
    ) ~- J: e. R3 A- p2 z
    9 ?2 N  c8 w5 H9 c1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:
    0 z$ {0 r5 p/ S6 f" ~1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
    6 N# y: ^1 _7 P7 l7 e# M$ p
    ' e: N& S/ H$ `6 B$ z6 L7 `2)假如你使用的是三引号,那么你也可以这样使用:
    8 n' P7 i! H! d% |! A6 i% K1        deleted = cursor.execute("""
    8 p" r/ m+ }+ I& N" w2                                 delete
    ' E. S9 R- _$ _' H" a7 W3                                   from products
    1 I/ F; {" q0 P; k# A; C4                                  where id <> 'pyodbc'
    & H$ E, d8 l4 f( W5                                 """).rowcount
    0 P2 ^+ r) R0 w/ S$ {+ R" `$ |  T: R& z1 P# K$ E
    3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)& u0 w2 x$ D7 P' X
    1        row = cursor.execute("select count(*) as user_count from users").fetchone()
    3 ?% m  B6 l, ^% U2        print '%s users' % row.user_count
    " @# S/ C2 y+ y. h1 k8 m  u
    3 i, y. ^2 v+ E4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。
    7 M4 L# V6 v$ B) e6 v1        count = cursor.execute("select count(*) from users").fetchone()[0]( a9 A  |0 }2 F
    2        print '%s users' % count2 P2 I; ^3 ^- M/ y0 p6 Z$ ?$ w! @/ a
    ! |6 T1 a! [, I) [. k+ k/ a
    如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。
    ) ^! p- o* K, G4 e9 F+ E2 @1        maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]
    & @) Z0 r1 `2 Z1 J: g0 K6 C; w1 g
    在这个例子里面,如果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-15 00:08 , Processed in 0.603258 second(s), 50 queries .

    回顶部