QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 6271|回复: 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、连接数据库
    + C8 P3 k( p) q0 p5 ?( f
    , N8 N+ b" [( a* j; s8 F1)直接连接数据库和创建一个游标(cursor)
    : s( t7 o, A' V( i4 i" d1        cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=meWD=pass')/ l, ~, X1 {. }* H; Q$ D7 h2 Q1 u
    2        cursor = cnxn.cursor()
    , O$ B- P- h( l9 @( c
    8 n2 Z5 H3 R1 ]) Q- @( e2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。
    3 W! J( z3 U+ @1        cnxn = pyodbc.connect('DSN=testWD=password')5 c/ u6 ~; l, x7 K
    2        cursor = cnxn.cursor()
    % \4 S: D# h  l* m5 M; h' c1 c' ^
    ) K- S. K& s/ ]# U# B$ H关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节3 q0 H  q7 X( }7 X' S
    , z; V( a9 W) k1 J
    2、数据查询(SQL语句为 select ...from..where)
    ) l2 f: T2 L" [* \7 J7 V( V) X/ r9 z9 S2 }/ @% U" ]% }, N
    1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。* i, k2 X; Y1 Q3 B8 @4 R$ }9 M
    1        cursor.execute("select user_id, user_name from users")
    4 f. a, }: y$ M& H2        row = cursor.fetchone()/ e* z6 k8 l2 g5 M( k( c2 U6 W
    3        if row:5 E* x2 {+ d6 {' T9 g7 n$ h# g& ~) m$ s
    4            print row
    2 i* z; j, l% z3 {# r5 L- z6 I6 f" r% V' j1 \+ T. i2 u
    2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。; \& ~' X) N2 h, L
    1        cursor.execute("select user_id, user_name from users")
    " z0 F" Y% }/ t% p8 E9 G" N2        row = cursor.fetchone()
    ( G& O& ]$ q' u( D5 F3        print 'name:', row[1]          # access by column index
    / f$ B' G8 Y& a7 A2 _4        print 'name:', row.user_name   # or access by name7 s  l- u3 K1 |3 Q. X

    $ c0 B" ?% M4 q6 M. o, h! C3)如果所有的行都被检索完,那么fetchone将返回None.% O/ u* ]; M  V# R6 n# I. O
    1        while 1:
      o' P, @/ B! N/ e2            row = cursor.fetchone(); t9 K1 }: L" h, L
    3            if not row:
    * x9 b  K# F2 _0 c4                break
    + j# P( h. ~$ S5 K5            print 'id:', row.user_id
    % H  d  x/ n! A% E, t2 f4 K$ d5 Z/ t6 h9 y1 j9 Y
    4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)6 s+ x* @3 D% y  B' S, S
    1        cursor.execute("select user_id, user_name from users")
    - M, P9 e$ Z* ~' |0 }0 Z2        rows = cursor.fetchall()
    / g1 O; G8 I; w) T8 `3        for row in rows:
    6 [; a* U7 c$ p' S/ Y/ H% W5 V4            print row.user_id, row.user_name
    ! [) m* o# u0 X: Q" a% `" u1 B, B* M9 Z$ k
    5)如果你打算一次读完所有数据,那么你可以使用cursor本身。
    ! }, C+ j3 l# k% w1        cursor.execute("select user_id, user_name from users"):
    . D8 l) |, r9 T, b. z2        for row in cursor:
    ; b) [  D0 h7 [1 H' p" K3 _3            print row.user_id, row.user_name4 W3 I5 R* J3 N/ Z3 H
    $ R1 J, N% s& Q; |% i8 P
    6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:
    6 a: d% o9 x2 v2 ?9 H7 |1        for row in cursor.execute("select user_id, user_name from users"):+ e8 F* S. \( B% X6 K/ H) J" h& [
    2            print row.user_id, row.user_name( z1 U/ a* D0 m  Q) |- z
    2 x9 _+ o- N9 m7 `! U- |# f
    7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:
    ; ], v" D6 h, R& ^- c. E( |3 y1        cursor.execute("""2 p! B% l0 T6 w+ q  F, |3 @6 `
    2                       select user_id, user_name: g' F  @9 p8 b3 g
    3                         from users
    / b' l9 i, Q4 L: d4                        where last_logon < '2001-01-01'
    8 t; @% \5 M; C( A0 L/ @6 q1 s: @5                          and bill_overdue = 'y'$ q  m! M4 J  X$ R0 M3 g' B
    6                       """); K! E" ?" c4 O. w$ B* @7 L
    & U; w  S: L: `* M
    3、参数
    * a. v3 a+ F$ z% Z' Q6 F. R2 J  E9 [/ w: v/ A' |9 ~; K
    1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。
    * x. B) J6 L$ l0 @1        cursor.execute("""
    , k7 e7 j! g. Q+ X- y6 ~1 H2                       select user_id, user_name2 ^( g) T0 x* B- i; x' `
    3                         from users
    % [5 V' P! b+ ~6 Z' m4                        where last_logon < ?: l6 r; O4 p0 ~. ~& K. v
    5                          and bill_overdue = ?0 Z; q$ \8 w9 c# I9 R4 q' f3 D4 ?
    6                       """, '2001-01-01', 'y')  b5 E3 d7 D1 h8 I- T
    4 P0 [7 u1 K. z1 l1 ~: J" }
    这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。' b$ e$ D+ X8 t, m4 }2 T' g
    3 e/ q. U4 X8 \2 X& P, K
    3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:% _+ _1 ^& v) }& k( y. J
    1        cursor.execute("""
    . ^# R  n4 e8 c: Q0 T: V% u2                       select user_id, user_name
    5 o- I0 y+ X5 K& e' |$ G* C3                         from users0 `. |* r4 d, s# |
    4                        where last_logon < ?* q. ]# S, o$ b* U
    5                          and bill_overdue = ?
    8 W  Q& r  @; |: ^0 h) L  s6                       """, ['2001-01-01', 'y'])
    * O, a3 O1 }2 K( A  W
    6 Y' z: j/ h$ K0 r1        cursor.execute("select count(*) as user_count from users where age > ?", 21). i: t  x7 P; w
    2        row = cursor.fetchone()
    5 ?. r; q0 L7 i7 a. A3        print '%d users' % row.user_count
    9 Y6 u* O8 A8 B8 q2 O' N2 M( F+ H3 _( @8 N/ D

    7 a/ w1 V6 Q) r
    * H, f) E; r/ W2 F4、数据插入
    ; a4 g. g" z0 m* a( e$ A7 f7 F  z
    1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。& Z" I* W' c! R( M$ W
    1        cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")
    7 l' ]; Q. f! B4 z& R2        cnxn.commit()
    & I1 V9 l1 H) S0 _' u" b6 g
    3 z# b% r1 ^* ~: i7 q+ x1        cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')4 a. F5 |2 j: X3 p* J9 P
    2        cnxn.commit()6 g( s1 S0 c: m! Q5 g. u

    " ~1 O- G& c% g' n注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。0 ?3 G- v/ t" [
    , Z/ e% K; P! }; D+ Q2 _- {1 M' w
    5、数据修改和删除
    ! r# _) {5 I! M2 ^7 M3 T
    " U1 `7 {5 Z1 y1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。
    2 U. R  x& F' y% |; z4 E1        cursor.execute("delete from products where id <> ?", 'pyodbc')
    " G5 }+ m7 O3 w8 R) d" R2        print cursor.rowcount, 'products deleted'4 F0 O; {. [3 ]* P% r+ ]3 H3 T. o
    3        cnxn.commit()
    ' C3 Q  l$ I* r# l: R1 W$ ~+ u# `1 X# ]8 S
    2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面), l# Y& I6 f( S3 f  r7 T% S$ f9 m0 s
    1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
    5 d% E0 ]  N7 Q* w7 \; Q4 y" V2        cnxn.commit()
    6 \% v5 F0 v7 _$ Q, ^& |: P6 ?- |
    同样要注意调用cnxn.commit()函数, p; G% L" B$ g, t  ^# A: a
    * _& H; Q7 |- N. Z  n, L3 r
    6、小窍门
    / L5 W2 W/ f8 a( Z6 Z. e) K; d+ F
    * I! X* o% H( r8 Y1 b' D1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:& v, F. D5 H; I! A3 J5 p- V0 p
    1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount8 E+ J7 r/ U: y. t$ G! _8 ]
    ! ~) ~  f7 F+ F4 I
    2)假如你使用的是三引号,那么你也可以这样使用:
    ( t  Y6 _3 f! x# D2 ~) o: F- b0 K1        deleted = cursor.execute(""": m3 g! B+ y+ y
    2                                 delete
    " X' g" X( E9 o  T7 w3 ~3                                   from products& R* q7 d, j3 b
    4                                  where id <> 'pyodbc'1 D# `3 m9 n9 ?, j  b+ }, Z
    5                                 """).rowcount
    ' T( l( L3 z# y3 @/ h) C$ Z! V* F! j# Q2 {
    3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)! f# |' z; [/ q' M2 w) q% _" V: B2 c
    1        row = cursor.execute("select count(*) as user_count from users").fetchone()
    1 w0 e6 C" h  Q" c) w+ @( z) K/ C5 J2        print '%s users' % row.user_count+ L: @. L8 m/ K2 G4 g2 ~

    # Y* B* f; b3 t! `' R3 ~4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。& ]% h9 x2 {" e6 v
    1        count = cursor.execute("select count(*) from users").fetchone()[0]
    + p- u, j3 w) o- g9 `- l* N. ~2        print '%s users' % count% L9 I" B2 e2 t$ ^# m

    - a% L* s7 i" S' Q: y5 J如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。  e8 B7 b! Z; Q% {, y$ l2 {
    1        maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]
    * {$ O: e' }0 H" `5 @$ U9 N! _9 [0 l& A, O7 ~! M' p- F
    在这个例子里面,如果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-10-9 05:23 , Processed in 0.296264 second(s), 49 queries .

    回顶部