QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 6145|回复: 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 W  k7 @2 q( Z; J9 ?) l! ^( E
    , Z+ P- {4 R) \& g6 p( g1)直接连接数据库和创建一个游标(cursor)/ f7 N$ e/ C% f1 D2 t
    1        cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=meWD=pass')
    , I# g  o( C: Y& v2 O- B2        cursor = cnxn.cursor()
    1 T( d- l0 r5 c# w/ l! N. h/ k) \9 A8 l. b* ]. s
    2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。8 M/ x+ I/ y* G1 P: |: B  y5 M
    1        cnxn = pyodbc.connect('DSN=testWD=password')
    & C( y+ x, O  r7 F3 h2        cursor = cnxn.cursor()/ A8 v" A! N+ w" _

    + [( X$ ~# s% w关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节1 L7 f- n/ G2 |+ X: E& r; k
    " V4 r% y9 m/ S1 D5 n1 x1 h" A
    2、数据查询(SQL语句为 select ...from..where)- d: T# L3 N2 z& E
    * ]# m( }; n1 c7 y2 `  N; e
    1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。
    : p) `/ P" l3 f! U1        cursor.execute("select user_id, user_name from users"); I, B7 k9 {. v/ Y& c; G6 \
    2        row = cursor.fetchone()6 K' e' J" x( s
    3        if row:
    4 e) U& V) `' ~6 g2 J- j4            print row$ L/ `4 w: }* |

    % |5 B/ A+ O+ V: A2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。
    " x) X# p! U) F3 f; k1        cursor.execute("select user_id, user_name from users")7 L6 U- B9 X, [( F7 _
    2        row = cursor.fetchone()
    5 w% c0 @8 ]+ b' L3        print 'name:', row[1]          # access by column index2 [; Y% l9 \3 ~$ v
    4        print 'name:', row.user_name   # or access by name! n/ i; I% _% C* v

    % s4 b6 N) [0 j( E- s3)如果所有的行都被检索完,那么fetchone将返回None.
    8 ~; U* O! Y6 F- U1        while 1:
    , {9 Q  @5 ]8 z5 O' b2            row = cursor.fetchone()
    # |5 h9 ^3 q5 Z8 k. u: g3            if not row:
    ' h5 K& x1 o- N4                break- {% f7 j* }; h
    5            print 'id:', row.user_id
    : c! w' G- Q3 l8 j, C4 D
    & C; Q) {+ K1 C# M4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间): v' x2 i/ y9 {: C" N
    1        cursor.execute("select user_id, user_name from users")( j% N( S, K  G& |! i
    2        rows = cursor.fetchall()
    / G1 H1 L; [: N3        for row in rows:
    8 {2 ^! |- [& N9 q4            print row.user_id, row.user_name
    8 T8 S0 ?; x& J, S3 m+ B! Y4 h
    " \- w) |9 A4 B( Q, H5)如果你打算一次读完所有数据,那么你可以使用cursor本身。/ J  M  d0 i6 V6 _. e/ v! z7 N/ E
    1        cursor.execute("select user_id, user_name from users"):/ M6 X) I, d+ V  Z) p' [) m
    2        for row in cursor:
    ' Z6 A2 H, _( \" U3            print row.user_id, row.user_name
    ( a7 o# @9 D. w% I7 D
    9 [' X6 j$ Z! R  J% q6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:
    6 K/ i, o6 _+ X1 L  Y1        for row in cursor.execute("select user_id, user_name from users"):
    . k. N" T6 Y  v0 ?6 V2            print row.user_id, row.user_name
    2 S4 G' C  G  G) C" c% {% ^2 N* S, f0 z6 T- y% M# @) A3 Q
    7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:
    $ c4 c3 v# z4 W3 w/ s: b1        cursor.execute("""
    ( [8 D; m) N. g6 [4 ^+ t2                       select user_id, user_name! K& W6 B' }% u: E
    3                         from users
    1 _' S) Q0 H; _9 r( g" O! W4                        where last_logon < '2001-01-01'. q# X+ E  n$ w/ g8 U! [
    5                          and bill_overdue = 'y'
    9 m: m2 V6 [) G+ s1 q6                       """)
    6 _+ `: j' M7 y0 u' d. r5 {8 m0 T8 z; q" P, @3 v
    3、参数
    . S# P4 g5 u8 p8 y3 G9 S8 C" m6 h; V& N
    8 P+ v! |/ r- d) Z3 }9 j3 E/ W1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。8 Y* _% z; a$ L  \
    1        cursor.execute("""* s" _* {: X/ |4 t+ \) ~
    2                       select user_id, user_name/ i' b- p/ Y. j) V% a0 q5 c
    3                         from users
    & f0 K+ L2 L) C+ W6 I6 v4                        where last_logon < ?4 b/ n1 z& R% G4 A$ x" M
    5                          and bill_overdue = ?& T, v7 Y/ p. Z4 Z! Z. q
    6                       """, '2001-01-01', 'y')4 G% z4 `$ I. l
      |0 i9 p4 M' G; T3 U
    这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。
    1 }3 J$ b. N/ G+ P  i
    7 X3 k0 z. W1 r  B3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:  L% t& E, y# B5 l
    1        cursor.execute("""
    3 e. A, k5 {4 |% F+ e  \# x2                       select user_id, user_name- s4 o: `; t9 N1 |: Z
    3                         from users
    ( Q6 r; u9 h1 F2 X4                        where last_logon < ?
    + _4 U( @* m5 w5                          and bill_overdue = ?0 J2 C) x! v& }3 A: @
    6                       """, ['2001-01-01', 'y'])
    % D8 G+ z8 U5 N( k) L+ ], m( y4 s1 E2 G; |
    1        cursor.execute("select count(*) as user_count from users where age > ?", 21)% m4 H# D$ D0 `; e+ S5 [: T
    2        row = cursor.fetchone(). J/ W9 ?/ M! U, T5 Q0 B( T
    3        print '%d users' % row.user_count: `$ i2 A8 l) d$ o9 }7 \

    ( Z9 i0 n4 h% C5 t 5 a* f; f4 z- M8 L" {9 s7 Y. Z
    2 ~% D0 V, H% x0 x+ O- i
    4、数据插入
    , x7 A# ?6 l8 R3 {
    6 ~- K7 R! ?7 S. ?+ Q" \  v, F1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。
      z6 ~( y7 e- [' X1 P! k1        cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")
    , M- f( q1 A3 M# o2        cnxn.commit()
    ! Y+ x) T, r) U+ |* ?3 `, Y% G1 K4 t/ J; M
    1        cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')
    : P' h' B! K" x2        cnxn.commit(): l( y. a/ i) c# X0 T

    % e( M! ?# }5 p5 Q6 y% V注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。
    - r7 z" ]# `, j$ X4 M" ]
    : {! t: J# ^6 I! I+ ]4 y& k5、数据修改和删除
    7 V9 ?% X7 s, C$ w4 s# B. H( Z$ @) Z, J8 n8 e! R8 z8 y* v( u
    1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。
    4 E/ v0 _$ R; D3 O: r4 K5 _  x6 z1        cursor.execute("delete from products where id <> ?", 'pyodbc')1 u# T3 p1 y6 h5 e% g
    2        print cursor.rowcount, 'products deleted'
    ! c3 ]6 ~6 t+ J- V# C# P' W3 _3        cnxn.commit()
    + m7 Q: g6 w0 P. U2 t* P6 E+ P& ^+ @
    2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)
    # E' @; Z0 f; a: X1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
    3 @, N. E3 I7 H5 {! K$ }/ p# ~' I2        cnxn.commit(), ^( C6 Z3 i9 N

      ]3 `4 C- V+ |6 y0 t$ L+ X2 ^+ {同样要注意调用cnxn.commit()函数
    4 j( x, g0 u" [- `) M5 n4 |  x
    6、小窍门
    9 d. t$ l4 b( b* `4 A+ J' C  ]5 U1 P, Z: A3 z3 e
    1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:
    1 M, @* }" r; A5 `  \8 X1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
    6 `" T8 M6 S- e' ?; f6 ]9 ^4 u; h# w& C/ j& w+ D( p3 ]) ~
    2)假如你使用的是三引号,那么你也可以这样使用:
    . ?2 h3 h0 H3 S8 d1        deleted = cursor.execute("""9 z5 P5 s% N8 E( f# X
    2                                 delete
    , P7 O/ W' H7 E0 j3                                   from products# b. }7 d9 a0 G- p" z
    4                                  where id <> 'pyodbc'
    7 e$ }# E+ C% b3 [  S- g5                                 """).rowcount
    4 ^5 n; p/ g% _& t9 S4 m/ _6 A5 L* Y9 p; r' l# i1 z0 U6 a
    3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)
    , H) r. Y5 P, q) [7 A  F* }1        row = cursor.execute("select count(*) as user_count from users").fetchone()5 K' h  s2 S4 V0 B
    2        print '%s users' % row.user_count: F' j7 e" V' U3 ~
    ; e- q( L3 F( y: i7 U
    4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。% |4 Q0 h4 B/ }! O3 h6 P( A
    1        count = cursor.execute("select count(*) from users").fetchone()[0]
      P" E# k: U1 H  T8 c4 a2        print '%s users' % count! O1 _, q( L* X
    % w) s9 F. n% g/ n
    如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。
    . Y' p1 Z' ?1 F2 |! J0 @1        maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]7 ^7 R7 v/ U" g0 w, f2 c

    0 z, |( A( G) L% n9 H+ s- r在这个例子里面,如果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:05 , Processed in 0.410765 second(s), 50 queries .

    回顶部