QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 6089|回复: 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、连接数据库0 a/ i1 S& H# ^" b' a6 e

    0 F$ G+ _  e2 b+ B- m/ K1)直接连接数据库和创建一个游标(cursor)
      H+ `5 g1 G/ s$ u' n$ C7 s1        cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=meWD=pass')
    1 k+ t( x" g8 u2        cursor = cnxn.cursor()
    $ f$ K- i6 k7 L' r6 b, g- X" b+ {( `. f0 |5 B5 j+ S' ^
    2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。6 ~2 Z( t8 H8 x
    1        cnxn = pyodbc.connect('DSN=testWD=password'): Y# Y8 |7 S# d# F8 h$ z1 G
    2        cursor = cnxn.cursor()
    9 D8 ^7 _: c5 Q. U) Q8 L8 V: F& G8 T* k& C3 _& |
    关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节
    3 s: Y$ q: v( A5 L4 A7 I0 e$ B+ Z% B# ?
    2、数据查询(SQL语句为 select ...from..where)
    2 ~4 g( d2 u. W( s; I% f* L; }5 |  W8 U4 j- D9 L
    1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。
    4 w  ~& k. y7 ?! q5 p! _' c1        cursor.execute("select user_id, user_name from users")
    0 H; m8 v  o3 R: A! p2        row = cursor.fetchone()
    2 y' P3 U  S. g3        if row:/ N' ^4 m5 Z2 v) h0 j, u+ M
    4            print row2 A& K6 }: m9 V- i
    * l7 D5 @! g, \+ ?% j
    2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。/ X: n* @$ o- _
    1        cursor.execute("select user_id, user_name from users")
    ! H" T; s& W2 G2        row = cursor.fetchone()
    / A* E8 I3 M1 i) a, g2 S3        print 'name:', row[1]          # access by column index1 x( q3 A8 I) N
    4        print 'name:', row.user_name   # or access by name
    + M7 j4 ~% {/ _9 ~' s3 W+ S2 ]
    5 W3 O, ?+ {# X. v: D+ n) e3)如果所有的行都被检索完,那么fetchone将返回None.
    % m; G+ Z/ @2 M' S: r4 w1        while 1:
    $ E; t: |# k; t2            row = cursor.fetchone()' m" g) a( L3 M* `* P
    3            if not row:
    + A- U) t0 v) i3 I5 a4                break: a- V7 Z8 V% K# ]
    5            print 'id:', row.user_id- u- O# w  }8 i- b; S5 ^

    3 l$ s9 K( X* Z5 u4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)( u, `2 ?) n' q7 M. v/ y# Y$ S
    1        cursor.execute("select user_id, user_name from users")3 i5 S) J5 W, ?+ B) s& S
    2        rows = cursor.fetchall()
    0 Y5 O# z) B6 b8 W! K; m4 J. t3        for row in rows:
    : m, ]3 V5 Q; J; A! C4            print row.user_id, row.user_name1 l4 b. Q  Q  s; G

    - [3 m* H6 y6 j5)如果你打算一次读完所有数据,那么你可以使用cursor本身。  w+ y+ g0 g6 M# n
    1        cursor.execute("select user_id, user_name from users"):3 E2 p* @! G$ Y! i6 X# F/ \
    2        for row in cursor:
    : l3 d; |$ m, |, m2 m6 u3            print row.user_id, row.user_name
    3 ~- e$ O0 Y) ^( l: H/ H: v
    2 B9 R, C+ K3 a( J# `4 z# c+ ?' i6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:, _( v7 N- D  h) r5 V
    1        for row in cursor.execute("select user_id, user_name from users"):( y/ J& |& |3 M% R9 |, O
    2            print row.user_id, row.user_name
    , p$ L! {0 U2 I% Y7 {, B; n3 C
    ; _# K- C# n' k4 L. ?/ ~1 c) c7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:7 F6 |7 y4 Q) n- m2 l1 H
    1        cursor.execute("""" Y  I/ I& H4 y6 u' U" H
    2                       select user_id, user_name
    4 \  v1 ]$ H3 ~1 y# g0 b3                         from users6 D- L" I- A1 T2 w3 u/ n
    4                        where last_logon < '2001-01-01'
    5 _* a- g) e! i5                          and bill_overdue = 'y'
    1 T" |. j, ^* w8 N/ I6                       """)
    " ]. u5 N/ x9 J0 n+ _) H# ]+ ?" ^# q! p+ s+ y# |0 t7 }4 T7 a! a
    3、参数
    ' G& Y( H- o) Y& m
    3 W, e& F9 a$ B2 M1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。
    6 q3 V" ]* d, o$ Z6 F- K1        cursor.execute("""
    # K& k/ P& w0 f  m5 D/ x% }2                       select user_id, user_name7 l/ j8 J9 p$ R9 D  f$ J
    3                         from users
    4 f9 ^' z1 N* L: r; Q8 l/ ]0 h( g4                        where last_logon < ?4 U5 W/ y# P* I  q) k
    5                          and bill_overdue = ?  e( Z( B: T  |5 f/ z& B9 F8 A
    6                       """, '2001-01-01', 'y')1 i+ z* f  R, V* n3 g: S6 E- \
    9 X/ t/ \: N+ M+ ^6 O# D6 D8 z
    这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。
    . l7 g9 P. [, n, \( z
    9 R/ c* j7 s* H! r3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:1 ?' t4 Y  n" J1 h$ ^$ u6 x; F/ O
    1        cursor.execute("""6 s% c' M' l' v7 R
    2                       select user_id, user_name# C  i6 L- t4 `5 _
    3                         from users) Q' }/ t, g" k' x0 K
    4                        where last_logon < ?* A7 v- y- Y4 ~
    5                          and bill_overdue = ?
    7 q7 F0 J! ?: w: F$ Q6                       """, ['2001-01-01', 'y'])
      n% A1 b5 l5 t" s5 B. a: T. [# q& X' f- }, g! t5 E: ]0 W  L" c, }1 ]
    1        cursor.execute("select count(*) as user_count from users where age > ?", 21)
    6 [) `. e! t/ c" t' k/ C5 t7 m2        row = cursor.fetchone()
    1 p( H/ y, a- G" y, N: v3        print '%d users' % row.user_count( g0 z/ K" ~" |% c2 F( p
    + g. @% `% \! y( {8 r1 a9 `) u7 D
    / b3 ]7 N1 x7 ^  E. \% E7 s0 K

    ; L+ m* W" N+ N9 r$ L4、数据插入1 y) ~2 [* b0 p! ^

    0 O! s" |7 k; X  ~; D' h1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。
    3 v* I/ C& y+ q, r$ X8 ^6 x" \1        cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")& B" w" D6 a8 A* i7 Y
    2        cnxn.commit()
    ( B8 c3 w: [4 U! {
    8 y" I- a4 F" Y1        cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')
    ) U1 k& v5 S+ k- u& \9 y* \+ I2        cnxn.commit()
    , @/ |7 p7 c% L  `% j$ \# H( R2 P# p( |: E3 f* o. s
    注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。
    4 p- n: _0 t7 C1 _( C, Z0 \) Y$ V  a" W9 H% f+ x9 h
    5、数据修改和删除
    4 t" w9 K2 ?' k. Q. x
    ! Z7 L7 v# p9 q, A3 f& B' b; v6 K1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。
    - y  I7 z3 Q% B1        cursor.execute("delete from products where id <> ?", 'pyodbc')
    $ j; M9 ^5 B+ a  p$ O% p2        print cursor.rowcount, 'products deleted'- [( X) q6 ^) B" }# V5 p
    3        cnxn.commit()! ^  E* A7 d: M4 j! Z! j9 Q

    : Y; ~; `: i* @1 @: a" }$ S2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面). u; V/ u* A! P$ s. c7 H
    1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount/ _  z! D- @( D* ~
    2        cnxn.commit()& ?& P, v6 C8 B% @! ]0 T- d5 Y
    3 f4 h: t! O7 J: ^1 c$ i6 |
    同样要注意调用cnxn.commit()函数# V" R2 g' ^8 `7 d
    . j* b  U' ^1 }0 T; `/ P
    6、小窍门
    # ?$ f$ V; E5 j( H; i( P0 I( J  g: S3 R: ^% w) C& [
    1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:
    0 o5 R! f1 b1 N# z* |  O6 e1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount$ d; e4 H/ r. w* G5 I; F2 l
    4 w' D& z7 Z$ m, U# L8 v
    2)假如你使用的是三引号,那么你也可以这样使用:
    : K7 i8 L& y5 g+ j1        deleted = cursor.execute("""0 N- i8 y9 v) e( C# U% w6 q: Z
    2                                 delete
    2 O, m9 F. x% b; l# r3                                   from products+ J4 L1 G1 ^9 t+ V  q. d# w. p
    4                                  where id <> 'pyodbc'
    6 y6 Q) ^7 H+ L. }; \5 \5                                 """).rowcount
    + F) L( ?* C, Y0 p
    ; p" y! v/ n2 y2 N+ J+ a3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)
    , @) U5 ]/ X* U1        row = cursor.execute("select count(*) as user_count from users").fetchone()( E. G( ]6 v# N
    2        print '%s users' % row.user_count
    4 D& b% f& G- w* Q3 `2 x  P
    : O' j+ P! [0 |3 h. C4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。
    * w; y) A. f& f& m3 b1        count = cursor.execute("select count(*) from users").fetchone()[0]
    / Y+ x$ [: G7 U2        print '%s users' % count
    - S7 V+ \' q+ D- U3 Y& A
    ! |" A* t3 K+ V0 y* y* K3 K如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。2 n! o9 j# U5 {; u- |: O( v, c
    1        maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]& y4 @9 C  \+ b. W
    # U/ P0 r# B* @9 _6 ^" {" g9 l
    在这个例子里面,如果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-4-10 17:38 , Processed in 1.735229 second(s), 49 queries .

    回顶部