QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 6182|回复: 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、连接数据库# a- u) w8 V: W: _# O, Y

    . V6 h& ]$ i8 w4 q1)直接连接数据库和创建一个游标(cursor)
    # a, y; k8 r6 }1        cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=meWD=pass')
      C/ o- `1 A2 e. v- M4 J; @2        cursor = cnxn.cursor()6 {( p( c1 R2 j0 P

    $ V* I# l$ e7 L4 _- ]6 W3 }2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。
    ' ^5 m; V0 h! O0 j: S1        cnxn = pyodbc.connect('DSN=testWD=password')4 j, f0 `; K0 D0 B0 Q
    2        cursor = cnxn.cursor()
    ) U$ k3 U+ q# I) G! k. y( o7 Y3 ^* a: w4 d
    关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节
    : G( P$ R" t! V: K) }1 W) L/ e# m% z& Q9 g, }$ ~
    2、数据查询(SQL语句为 select ...from..where)
    - l4 u; Y5 r3 ]+ J0 S( F2 R
    7 y& r; c$ x/ A: a; Z1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。
    + h1 o1 g' f( V  H/ p1        cursor.execute("select user_id, user_name from users")
    0 P' b/ x' k0 a4 l/ e2        row = cursor.fetchone()& S' i) N2 k, I7 d: |
    3        if row:
    5 E7 r6 Y1 A) V4            print row- [: q- i7 V4 B5 J
    * @! a# y( d5 h/ l7 O  S5 a
    2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。
    ; |0 J- L, T  m# I# l4 R, W0 V7 ~8 M1        cursor.execute("select user_id, user_name from users")
      v" R% T6 D+ |& R$ W2 H2        row = cursor.fetchone()
    . i7 N! o, k% R; h3        print 'name:', row[1]          # access by column index
    % H, F8 O- X. \/ c- n8 G4        print 'name:', row.user_name   # or access by name( I& ^2 `8 n) l, b! ^2 R! l7 K

    # Z% X8 W% \3 L" ]- ?& N3)如果所有的行都被检索完,那么fetchone将返回None.% J7 \$ e4 k, l9 A  ^; `) m
    1        while 1:
    " s7 f4 n6 e- J' h6 j: ~2            row = cursor.fetchone()
    5 q/ g5 T0 M2 y3 y: G1 ~  h3            if not row:
    * |$ F: Q" q% G8 y6 y9 d. H1 ?7 n4                break$ o) c) e2 w" D9 ]" R
    5            print 'id:', row.user_id: x0 {( W3 a& J6 w6 |% x" N
    * w) H. i0 u- A: V9 ?+ W8 t
    4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)  Y! f8 \/ x" _8 m9 C7 ?: Q
    1        cursor.execute("select user_id, user_name from users")
    + K, E' o$ T6 d. a$ B2        rows = cursor.fetchall()
    ; `& z+ X7 b+ R8 c! C! ?3        for row in rows:
    . z/ S4 o* ?" Y! A4            print row.user_id, row.user_name
    9 u8 x+ _, B% M, ~( [, z$ y+ b- f! X: O0 V6 S' A3 D5 s
    5)如果你打算一次读完所有数据,那么你可以使用cursor本身。
    3 `" y" i1 b4 t& g0 ^9 d( D+ r8 h8 `! C2 M1        cursor.execute("select user_id, user_name from users"):5 B" N- X8 G( U6 n3 N1 B
    2        for row in cursor:
    ; |0 Z& ^. X: J! t- Q1 D3            print row.user_id, row.user_name
    & q) h' a# x" ~2 V; ?* O( W" p
    8 n0 V8 ]$ i( n- Z6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:
    " K* o# d6 ?/ m' g3 E1        for row in cursor.execute("select user_id, user_name from users"):: L! ^/ _8 j- B: S+ R% z) h
    2            print row.user_id, row.user_name
    $ {4 e6 _" s! s1 R# I: P
    / x% Q, Z3 M5 s3 U, I$ j7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:
    - h2 E2 L% U% u: w; J- A" P1        cursor.execute("""- S" R& l" K1 q0 J
    2                       select user_id, user_name, b; x8 _# ]* |' f: }1 H; K
    3                         from users4 d6 h0 b+ i: R- Y  L% ~& e
    4                        where last_logon < '2001-01-01'9 I% p3 k. S# e, |" k7 ~* K' W* z, Q
    5                          and bill_overdue = 'y'
    / a3 E( g$ B& c1 C9 u. W6                       """)& y- q5 R7 D+ ~' k6 x, u# G
    7 O4 [. z; C# j- p5 L" {
    3、参数4 d, H+ p) E6 T- t1 w6 G; S( \' z8 A
    $ T3 b5 o( W2 j! ?' L" A2 [
    1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。
      L9 w1 a5 X1 |+ t3 q1        cursor.execute("""6 J' K! K$ h% L! o9 ]5 h
    2                       select user_id, user_name( }% Q# ?% ^1 O- r/ [
    3                         from users
    9 U3 s; U1 Z7 k/ `1 Q7 {7 c6 f4                        where last_logon < ?
    & [' f5 A& h+ q3 X( J, W5                          and bill_overdue = ?( [/ B& z, ]( A' ]& R
    6                       """, '2001-01-01', 'y')8 C+ |# s( p$ p8 c! c4 @3 [0 @! S7 p

    5 _4 J& C0 V; j; s8 P这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。
    ; X8 z2 w' k( m9 {- {2 w" _8 N; W( a* i% T: s4 [6 W4 ?
    3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:
      F# h( q+ {, {( v1        cursor.execute("""
    ( ~. D! v- ?& M% X5 F) \7 C& M2                       select user_id, user_name
    7 N% [7 ?( ]8 I1 Z) T( G+ D3                         from users" k: C% u+ w+ }0 v
    4                        where last_logon < ?
    5 H/ G# u" z! Q5                          and bill_overdue = ?1 e8 h1 w: H# L8 l# t. V
    6                       """, ['2001-01-01', 'y'])1 y% w8 m' ]& @, X5 J$ {- G
    * f, q. |' q1 N
    1        cursor.execute("select count(*) as user_count from users where age > ?", 21)1 g" q4 y4 G$ i; D
    2        row = cursor.fetchone()+ t. R# ^3 r, N' y5 H
    3        print '%d users' % row.user_count
    . O9 X9 O) x/ N! @- n5 `6 f9 k( S6 f, l
    8 p% W! ]4 M# f: _
    3 r8 @1 ]; K/ ]1 P
    4、数据插入2 \3 d* m' ~6 U5 L; T4 T; {

    , n( h* V8 q! n" i& o8 o5 P1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。/ f( l/ |4 g  o% e( ^7 `2 y
    1        cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")
    5 \" [. J* b9 Y% ]% d& j: R2 a. c2        cnxn.commit()/ f, M8 c! ]9 O2 [. B" V4 v7 y
    * J) f! ]* v+ n0 q! I4 g
    1        cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')
    & R- u" l; C1 f4 A$ M% a+ |2        cnxn.commit()% P2 S( s* {6 _6 O4 n2 \: ^
    - D) A4 P& _. t, M% Y/ R" e$ O
    注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。
    1 J7 g/ E7 ~7 e( e2 h
    7 s! j& A! D( ?8 D, t3 l3 R5、数据修改和删除& I. D  T( G4 i7 O6 V! v) H

    5 ~. J# ?/ J+ E' X1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。; W+ H) U! U0 e* N$ d) w, O
    1        cursor.execute("delete from products where id <> ?", 'pyodbc'); d3 S% C, W5 G9 a# a' `# V
    2        print cursor.rowcount, 'products deleted'
    : B' }  @8 F2 r0 w' v3        cnxn.commit()
    7 _2 _/ L# L* q3 A& ?5 u1 J% s9 W- I$ k1 H" m' r# J0 S7 I
    2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)
    ( Y( {3 A! ?) @, g& [& x1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount0 l: f* A& L' ?
    2        cnxn.commit()* m$ U% |2 M3 C" l2 N3 x- h
    9 u( _1 b8 [/ Q% A
    同样要注意调用cnxn.commit()函数
    / C  I, H! ^) l$ Z6 D* {
    3 H9 r: R8 L: e% p+ [6、小窍门. B% _$ i! j( r
    ' X7 M' k% G+ N- b
    1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:! i1 l$ O& \/ \- t, n% [
    1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
    % t4 Q3 c/ K0 ]6 d( N+ m; i) O: c8 G: Z/ [- T
    2)假如你使用的是三引号,那么你也可以这样使用:4 I3 ^& m* n2 C4 L  O0 a
    1        deleted = cursor.execute("""1 X; n6 j% L0 E3 I0 F8 S
    2                                 delete2 ], r. ]$ X+ a1 r! h! H
    3                                   from products
    % |1 |. D* u: ^  j* V! x9 k; A0 Z  |4                                  where id <> 'pyodbc', P. h  l  v. F- D. P8 _5 ^
    5                                 """).rowcount- D% _4 V- N" r) b' G

    ( w3 r( }  r) C: n% V' l( u  W8 W% i! Z3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)
    4 r- g1 C4 h9 G5 B, }2 _1        row = cursor.execute("select count(*) as user_count from users").fetchone()
    , c/ U$ D8 R  j0 I% a$ _2        print '%s users' % row.user_count$ A. L3 v" E& _2 \
    8 b# n1 I% H2 z8 p8 d; B# o% ^' U
    4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。
    5 v$ Z% Y" i1 f7 I9 R  {7 e1        count = cursor.execute("select count(*) from users").fetchone()[0]2 g# I- _) y* I! f& I& _. I( I
    2        print '%s users' % count
    ' M4 |5 a+ s. v* _. ~( g" G& |8 n# d" Z- A  M
    如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。- u2 U8 `$ t; `+ J8 k$ I0 b
    1        maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]5 W5 Z7 M0 A6 H- f

    " Q; y- t: |7 P5 n: [1 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-8-23 05:48 , Processed in 0.396051 second(s), 50 queries .

    回顶部