QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 6174|回复: 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、连接数据库& q, M! U  e2 G
    ) l, Z) a; X- r$ t. P
    1)直接连接数据库和创建一个游标(cursor)4 ?  `1 }0 c/ t. ~
    1        cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=meWD=pass')
    $ G. T  t+ S8 J! l" m2        cursor = cnxn.cursor()
    0 f8 _& t$ R0 r& W0 D/ C
    * x8 \$ V! ~7 R7 _8 R2 x: L2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。
      C' k, J, }% N5 r1        cnxn = pyodbc.connect('DSN=testWD=password')# a" L' }, ]2 J; o& A4 a
    2        cursor = cnxn.cursor()
    . b# d# g* {" n: ?- z9 j2 y( I4 G! d
    关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节
    . C3 s# k, e* j7 W2 I" ]0 ?- j! j8 l; v# ~9 ~/ [% n# ~) w8 a
    2、数据查询(SQL语句为 select ...from..where)
    ( }' e& D$ L- T5 i, |5 k; L+ y* m+ }: u; h6 ^
    1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。
    0 Y5 K0 s' ^! X4 C6 F1        cursor.execute("select user_id, user_name from users"). p7 Y& C' S3 m  i: y: P
    2        row = cursor.fetchone()
    3 t' X+ p8 d4 Y3        if row:
    6 U% }" M( G  R! @4            print row, J! C( R* J# x6 N6 m& `8 v

    ! N" z' l# r! Q! J. Z2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。, P8 o4 g$ ]( Y/ }( O9 U! U
    1        cursor.execute("select user_id, user_name from users")
    ) @# T$ n8 f% f2        row = cursor.fetchone(); u  V5 |, x9 X
    3        print 'name:', row[1]          # access by column index
    ; M. b* N/ I1 y8 R4        print 'name:', row.user_name   # or access by name
    7 f* _/ S( N* b2 U3 `
    # F1 w' {5 F; B$ }2 X! D3)如果所有的行都被检索完,那么fetchone将返回None.& D8 Y1 {- n6 V
    1        while 1:: c. c  p6 c/ |; ]8 o
    2            row = cursor.fetchone()  [: B8 N( o) i3 n2 c7 Q, t8 I
    3            if not row:# B' D9 d: l% [4 I  O! r* C7 {& C( ?
    4                break
    , P5 E+ P7 D3 V3 ~3 B5            print 'id:', row.user_id; o- H4 `0 y2 s0 d4 M0 ]) r5 K

    ; ~# J$ X9 n! |$ A, y5 D4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)
    9 e+ Q$ C* a5 ^* m9 I2 \- \1        cursor.execute("select user_id, user_name from users")
    7 v3 w) Z  R* u% e, f2        rows = cursor.fetchall()
      p4 ^- R  @! Q! m3        for row in rows:; t1 N" u) b+ U2 C
    4            print row.user_id, row.user_name
    ) T& c$ E. s7 n0 L9 Z" }) ~4 G2 T
    7 q7 z% r2 J( A# E/ L$ G5)如果你打算一次读完所有数据,那么你可以使用cursor本身。8 @( F7 o% V0 d  |
    1        cursor.execute("select user_id, user_name from users"):% Y; h$ \( S' o+ N" i5 w
    2        for row in cursor:, _: l5 w7 S. w& X
    3            print row.user_id, row.user_name
    ' ], h0 m8 J! Y! F) ~! `' X) W" r# `2 R' Q
    6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:1 X; ]: y- C2 M! W
    1        for row in cursor.execute("select user_id, user_name from users"):
    9 @" u) u. V4 W2            print row.user_id, row.user_name- T8 B( y$ n$ `- C; K% f
    ' S5 B! A. v4 R' R8 o' t
    7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:& f. g& f5 \# H& A; ]
    1        cursor.execute("""
    0 `8 J: v4 w5 `* n2                       select user_id, user_name
    7 d9 `0 m7 v9 v/ r3                         from users
    " H; S" L& k7 N+ l4                        where last_logon < '2001-01-01'
    1 c: \- q' A1 |. X8 ]. Y! c% z5                          and bill_overdue = 'y'
      L9 l8 M  Z$ @& U6                       """)
    0 c) n- C; E4 X+ ?& x
    7 P# {- ?8 C+ t: S$ D8 N3、参数* j" \; D6 q# r# C
    . `3 N2 F* V' ^3 k/ Z4 |, b) r
    1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。
    8 M# J# `5 ^" w1        cursor.execute("""
    9 s* D; B2 z7 G. l2 ?0 ]! Z6 }2                       select user_id, user_name
    & z4 f7 U% n* Q$ R( G3                         from users% `8 ^: u: O* o1 k, ^
    4                        where last_logon < ?
    - M) m( H) u9 J; [" C5                          and bill_overdue = ?
    9 i% L/ v; r! V& @. v, H6                       """, '2001-01-01', 'y')
    ! \" I' r& V6 P% B9 c  E) U. q8 k8 p8 `1 `+ n9 h( h! t# L
    这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。
    7 F9 ^( O, v, r* [+ A7 |  y. ]6 f( F( H; y/ N# c
    3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:
    ; O1 h* g- s' h+ @7 r0 q1        cursor.execute(""", X3 L) ?/ H  [3 K
    2                       select user_id, user_name
    0 k* L) L+ o2 h3 [' _3                         from users! ~% S1 e7 Q. g
    4                        where last_logon < ?
    4 [& E7 r! j2 P# g+ a1 z: V, R5 [$ I, U5                          and bill_overdue = ?, t5 t/ N3 i  B+ A% h$ s
    6                       """, ['2001-01-01', 'y'])
    " W2 G! z6 \4 z- N) F' U/ k8 B# A% n3 P! s+ V8 ^
    1        cursor.execute("select count(*) as user_count from users where age > ?", 21)+ t' k$ e' _. t# K3 r; B; Y3 ^/ ]
    2        row = cursor.fetchone()* |4 i# i) u& O- k' g% K
    3        print '%d users' % row.user_count( l3 t: e1 M- Y$ ^

      H+ @. b2 w$ ?, k2 N% h- K/ l
    0 x+ S7 P* u: h% ]$ V5 z9 u3 p+ o' W! {" y
    4、数据插入% m8 n. C2 w/ ^+ K* J1 i5 Z: u5 H

    + N- i9 j( A  _( e6 {6 b* b- _1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。+ ~* n+ e1 e) s, d" |
    1        cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")5 L. E, e: P: ?8 S
    2        cnxn.commit()
    " E& ^+ R  s) l/ r, I. P; w* F
    / }2 M) X! `8 Y  H6 O1        cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')
    + R+ [( S: l/ b2        cnxn.commit()# t5 Z8 L: r0 n

    7 w1 q% R0 {0 P8 L注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。- f. y4 U9 M' x$ k  [6 r

    & g& P# O; b& A5、数据修改和删除2 q0 X& ?1 w" @' `3 U4 [% w
    1 ]- X& i) V/ V% w( l6 R9 a
    1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。% [" _* A0 `1 j( l. S. r
    1        cursor.execute("delete from products where id <> ?", 'pyodbc'), o! i; R6 D1 k8 p% z+ _: p+ l; P, {
    2        print cursor.rowcount, 'products deleted': a: N7 r* j$ d1 b) z% a- C8 R! r( i
    3        cnxn.commit()
    : z* @9 g2 ]& }+ U
    * F- A) n+ z% m) h& ?$ e; V2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)
    9 A" `* d" W! \" y$ g  c1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount! \  K+ X' o. Z. P
    2        cnxn.commit()9 ^. j! _8 o4 s4 l* }& |

    * d, Q0 x; R) ~0 `( ~% t! S: H同样要注意调用cnxn.commit()函数* Y' y) ~3 I" r' C! |' q7 e
    4 G! f5 T% Y8 Y' C1 f0 ~
    6、小窍门
    " A6 X: U9 z2 C* ]5 f) v' h0 i5 P
    - t( i: W. Z* M2 L1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:+ s! u! H6 y" p" X9 D- A: x
    1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount; `& f& ^) z4 l8 j0 R
    , @8 Y. K) x, |
    2)假如你使用的是三引号,那么你也可以这样使用:
    - Z1 ^. u0 ^& e+ ?0 C1        deleted = cursor.execute("""( X4 F/ M/ h6 P6 v( `
    2                                 delete
    $ z$ y9 a1 {; w# u& w7 W3 J9 l! K) j3                                   from products! ?( m8 a8 f5 v/ D
    4                                  where id <> 'pyodbc'  p, \' }! b* |8 y8 j4 O2 {7 L: c! I! L& r
    5                                 """).rowcount
    % P- E- P  z% W& I. [
    + U( f, ]$ Z0 s  g9 e% W+ m3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)
    ; x8 |. G  |, B) D1        row = cursor.execute("select count(*) as user_count from users").fetchone(): k3 ]1 l' w3 V1 U; m
    2        print '%s users' % row.user_count
    " g' M; Y6 L) ~
    4 d; b- e6 O% C+ S- f9 T8 l. Z  G4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。
    4 K/ n0 F, r9 J  ~4 Q* a% q# y1        count = cursor.execute("select count(*) from users").fetchone()[0]
    & T" y: J+ e& R2        print '%s users' % count2 G5 _- f1 V( `4 w- ]' W
    ' p$ R9 t* S9 t. N; R7 e( P. \
    如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。- P  ]0 n0 f7 z. K  ]! j  P( E
    1        maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]
    & _# S2 C7 r: _2 Q; L! P8 O. e, n& U% p
    在这个例子里面,如果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-8-4 18:47 , Processed in 0.408691 second(s), 50 queries .

    回顶部