QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 6177|回复: 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、连接数据库
    + @$ f  j! o/ z; i% m' B+ n7 V* Q- B. H' J
    1)直接连接数据库和创建一个游标(cursor)
    0 W6 R% {3 o5 k2 ~. }1        cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=meWD=pass')
    9 P% M* y* H% \1 ^- u& t2        cursor = cnxn.cursor()
    . G6 f  ~  o3 N# d: U; ?
    ! u$ w* z+ ?/ P% a$ L& F2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。, K+ J- K7 l* {- }* V5 e' E
    1        cnxn = pyodbc.connect('DSN=testWD=password')- j# W, R7 Y' @2 R# x
    2        cursor = cnxn.cursor()  c3 |0 _3 E# i6 ?0 F- ^6 K

    ) q% Y- A1 o7 F! _; _1 K关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节1 E% k* z- r' b, A

    : a- @! R4 B: ^4 t* I1 X8 N2、数据查询(SQL语句为 select ...from..where). v0 W, O% h: W( |. V6 \

      v8 N0 ]+ R9 b+ M1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。
    * f6 t1 P' e1 F7 r9 Z' i( R1        cursor.execute("select user_id, user_name from users")
    . H/ P/ ~, Y& Y' \+ e+ u3 u2        row = cursor.fetchone()& o+ v5 d8 u2 z
    3        if row:
    - B# T/ D2 m9 \& I4            print row5 I0 H% W" y' F) U$ O! z

    " d  R* y. @- |* Z* z- Z! p7 h2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。
    / p: Y8 Z3 ?1 i. P5 n, `: h3 \% E1        cursor.execute("select user_id, user_name from users")
    + t9 Z8 u+ C. a3 p4 Y* P. a+ e2        row = cursor.fetchone()
    4 ]6 ~( [' B. J8 Y3        print 'name:', row[1]          # access by column index, R# S  V8 V# O% h9 R, W
    4        print 'name:', row.user_name   # or access by name/ i% S. P. Y0 ^: b
    % J  e' r+ Y. s! l
    3)如果所有的行都被检索完,那么fetchone将返回None.
    - @5 E- \7 u) F' ?5 h( V1        while 1:
    # \0 s. Y$ i3 o7 y/ V! l/ `# Z2            row = cursor.fetchone()
    - ?. J. a9 H# u) S3            if not row:
    , B6 x. q. A9 M# Z6 h5 [4                break8 u# R# }8 x0 N, H
    5            print 'id:', row.user_id6 {6 h, A. l6 a6 i
    4 a/ l* Q+ x3 \
    4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)9 b# V" {0 z0 V
    1        cursor.execute("select user_id, user_name from users")& C5 ^  n. S9 i* r& z5 z/ T
    2        rows = cursor.fetchall()
    ) a! E0 R1 P' w1 x& a3        for row in rows:  J  T) q2 v) v. ]
    4            print row.user_id, row.user_name
    ) U* L+ Q; A  o! c
      r( I) E! D; r* A* F5)如果你打算一次读完所有数据,那么你可以使用cursor本身。
    - K/ ^5 t3 k9 C6 `0 v! q1        cursor.execute("select user_id, user_name from users"):
    8 y5 E1 u6 H/ @; V- a9 K2        for row in cursor:
    ( N* I# f- t5 H7 d3            print row.user_id, row.user_name
    2 z4 X1 n  `2 f1 Q
    7 a2 M5 H9 T/ N( w6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:
    2 e: @, |4 [$ W! W1        for row in cursor.execute("select user_id, user_name from users"):
    - D3 A0 O" j: M5 @% M, q# E2            print row.user_id, row.user_name
      M  z& _: T4 h6 r6 h" m  ^2 ]
    + }9 X" d- }& f! N: H# e, u7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:3 ]- r0 B  V& m3 j
    1        cursor.execute("""' J: M/ A, r7 }) [% I
    2                       select user_id, user_name9 c* e. F9 H9 R6 o- w% V' J$ _7 D8 i) \
    3                         from users# t- P0 r" ~. i* [# c
    4                        where last_logon < '2001-01-01'6 V  b" Y! _" R+ k- T* a
    5                          and bill_overdue = 'y'
    # j% A( c9 ^) q* M6 r6                       """)
    : @8 d2 X4 Y0 j) i$ ?) T- B* Q/ ?+ f. m. y
    3、参数
    % t* q2 w) B3 Z0 y6 x0 V0 B) s7 G. n& s2 U; X# w; u
    1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。/ s6 i2 A" N& X1 a4 u. p
    1        cursor.execute("""6 s4 }0 p  v  ?6 W/ g2 v$ L. T* z
    2                       select user_id, user_name
    ' B( G- r/ s' \' [# X3                         from users
    5 J6 n6 s3 o% Z# y* k5 d$ T& c& X4                        where last_logon < ?0 Z) m( f2 Z' H2 U1 `* {6 K6 \
    5                          and bill_overdue = ?; s+ J% J+ r: J$ [
    6                       """, '2001-01-01', 'y')' A/ M$ C, I- V4 E# ?" k+ t

    . U2 ~0 U' d5 T8 Z" \这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。2 |; p- }" o# Q; p) ~; c; k& y; k
    ! F# v8 r! ~6 _$ `0 Q$ y: p
    3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:
    % m! [+ n* E5 ~. v1        cursor.execute("""& ?$ F% K7 a" G% o$ \5 O& C
    2                       select user_id, user_name
    ! e9 ]8 Z/ s" X6 w1 ^  p* j+ h# j( S3                         from users
    " y, X3 X% v, ?  ?  f4                        where last_logon < ?
    3 E- o9 I- d1 |5                          and bill_overdue = ?* U; C( k8 P2 \/ X+ k& `( G
    6                       """, ['2001-01-01', 'y'])" n! o. l  ~& c* B1 _4 w" v7 h
    ( g7 {& Y- K' s; B. E- P8 }
    1        cursor.execute("select count(*) as user_count from users where age > ?", 21)# F. ^! N. d( h$ b& }% D, X
    2        row = cursor.fetchone()! V8 M" [" W1 A/ |/ d& ?5 d
    3        print '%d users' % row.user_count" ?; |/ ^, _' z0 D9 l. G
    9 L' q* W* r0 @+ J

    % ^0 D  o8 s! c3 y' ?8 q" W; }, e# Z; e# a/ @& }: c$ Z8 u
    4、数据插入2 [1 H6 u1 C: t$ ?6 P  q; c1 ?2 a
    " e# }3 F( N2 f( l& F, G
    1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。# ^6 c. Y# `$ X, `- J
    1        cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")) r1 g1 X( ^8 P6 {0 G* ]! |9 \! Q
    2        cnxn.commit()
    1 z  p4 P9 F5 Q1 t$ Y. Q. T1 r, t% m
    1        cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')
    . o( i& b  }) h5 ~) O$ h# q6 L2        cnxn.commit()
    5 X0 K+ k$ w7 @' k& Z/ H* ?. R: W4 m4 l/ v. [
    注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。
    " m; {* Q8 e# |  ~# O3 n8 m- Z; D2 ?3 G% K6 s5 A% c+ _
    5、数据修改和删除  C. u8 S: r/ B& t( j

    : \# D3 W+ X3 w% `% N1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。
    . e1 S8 n& F; e" k% y! ~% ^1        cursor.execute("delete from products where id <> ?", 'pyodbc')8 ^) d. F  l  |
    2        print cursor.rowcount, 'products deleted'
    # v! S7 l" G# q0 A; ^, c3        cnxn.commit()+ l9 x# g+ B- u3 [/ v

    1 s9 P" ~, Y$ G) _2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)
    1 d! X& s9 x7 v7 \8 [0 I  o1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount6 O, ^, p9 j) i4 Z2 ^. t
    2        cnxn.commit()
    0 Z+ Q3 M1 M5 F: j3 V- D" U4 a2 w
    ; x& ~" U3 b3 {5 n同样要注意调用cnxn.commit()函数
    , \7 p9 K) U/ Y, B- ~
    1 |& q/ Y. e, y2 |  w5 u6、小窍门
    ( |' |; M7 e9 Z1 V0 z; ]3 V& N2 o' K
    1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:
    2 I% e8 n3 B- z; t" j$ s* F1 }8 ?1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
      i6 v- q6 k# q9 m; C: I! z% v
    ) b, @* T8 q& j& O8 E2)假如你使用的是三引号,那么你也可以这样使用:
    ; y& r% I5 x" u' {( ]1        deleted = cursor.execute("""
    ' T. R  T* z' [; R& D2                                 delete/ X' F4 {' i! I9 O2 x/ r( ]
    3                                   from products$ f& E, m1 M* G* N2 j& k# U
    4                                  where id <> 'pyodbc'; u( [8 E) c2 t4 J8 s% T
    5                                 """).rowcount
    / z$ |" U$ _/ \/ \- K; ?
    # c' j/ V! A6 w" t  o3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)  l9 ^( G/ Q3 ?! G. e  x$ @
    1        row = cursor.execute("select count(*) as user_count from users").fetchone()
    3 i+ f# g2 c+ L6 c( e+ X5 ^1 j2        print '%s users' % row.user_count' c+ w) n( N$ Y* t

    6 d7 j# F' H1 N3 g2 m4 h4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。5 H* `, l! \/ O8 v/ G" I" Y
    1        count = cursor.execute("select count(*) from users").fetchone()[0]
    4 v* p( k, d' K! O4 I3 f2        print '%s users' % count& U; ]. z) o/ ?8 c5 T, ~

    ' |1 r2 v+ U1 X如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。0 K7 p2 D5 n/ U: Z$ t% R
    1        maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]
    0 |1 Y( S) a/ X! \" Z* G5 M+ C* x$ R7 `( O6 ~
    在这个例子里面,如果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-5 07:24 , Processed in 0.767878 second(s), 50 queries .

    回顶部