QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 6087|回复: 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、连接数据库
    & r: U2 t" E$ Q! H  ?) F6 X4 z% Z, h& x' |/ ~! {2 ~
    1)直接连接数据库和创建一个游标(cursor). |' z0 [8 U6 {$ H- u  e9 K* W, T
    1        cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=meWD=pass')! t- {5 F5 p. W+ m( |
    2        cursor = cnxn.cursor()
    7 i( w* U4 i/ y( K: d9 Z: I; E* J! g) U0 L
    2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。; M- }# W. u! t+ D+ |
    1        cnxn = pyodbc.connect('DSN=testWD=password')/ [* `# @! V  z) |
    2        cursor = cnxn.cursor()
    ( X' |6 Y9 G( P, r9 p" P
    # ^2 S- }3 v, T0 L关于连接函数还有更多的选项,可以在pyodbc文档中的 connect funtion 和 ConnectionStrings查看更多的细节6 e9 f! e* u0 ~0 ^

    % C2 @/ G# V( A/ g8 E2、数据查询(SQL语句为 select ...from..where). _$ M& w! G5 K7 {# t# K: n
    : U9 E+ g, x8 K6 ^; m
    1)所有的SQL语句都用cursor.execute函数运行。如果语句返回行,比如一个查询语句返回的行,你可以通过游标的fetch函数来获取数据,这些函数有(fetchone,fetchall,fetchmany).如果返回空行,fetchone函数将返回None,而fetchall和fetchmany将返回一个空列。6 u3 F/ U3 J9 }! H2 Y* R
    1        cursor.execute("select user_id, user_name from users")
    $ K: V# Y% O, Q" E: R& Y2        row = cursor.fetchone()
    2 c# ~* r4 v3 j$ J4 X6 Q  i, [. v6 n3        if row:
    ! i' F; n& z0 {- t9 ?% `4            print row
    - t4 U( u" ^# J4 n& n# _
    2 o1 z2 Z% j! ?& Q2)Row这个类,类似于一个元组,但是他们也可以通过字段名进行访问。5 e- M% r1 ?: E; R# y8 a
    1        cursor.execute("select user_id, user_name from users")
    2 }% f6 L' u+ ?& Q1 g2        row = cursor.fetchone()4 e$ W6 t& Q' ^* ?% @# [
    3        print 'name:', row[1]          # access by column index0 C: w6 A' F4 e( i& j
    4        print 'name:', row.user_name   # or access by name
    - q$ B! z5 N& C/ E) A" w
    ' V1 h6 w0 F7 U3)如果所有的行都被检索完,那么fetchone将返回None.
    3 E: t, j+ X6 u" I0 k) h1        while 1:& \3 w8 @$ U4 B( c5 W( X
    2            row = cursor.fetchone()
    & G# Q. W- }, A0 m  k+ O3            if not row:; z0 @5 ~/ v& D& T
    4                break
    & {4 B3 n4 S6 f9 A5            print 'id:', row.user_id
    8 |$ K1 M# i" |; v: Y8 ?6 |
    3 C. L4 b& |/ Z# ]4)使用fetchall函数时,将返回所有剩下的行,如果是空行,那么将返回一个空列。(如果有很多行,这样做的话将会占用很多内存。未读取的行将会被压缩存放在数据库引擎中,然后由数据库服务器分批发送。一次只读取你需要的行,将会大大节省内存空间)
    & Y& y: |/ ~9 K1        cursor.execute("select user_id, user_name from users")
    0 a5 @' ?$ g. \8 \& e# i2        rows = cursor.fetchall()
    ' S$ f  j. E% x( |! u3        for row in rows:
    # f9 c- h0 V) ~: [8 p4            print row.user_id, row.user_name+ w- r: }. w8 t$ B7 N7 {

    1 g. ?6 W: h; @9 y5)如果你打算一次读完所有数据,那么你可以使用cursor本身。/ t. S9 b% C# b4 `( P: N
    1        cursor.execute("select user_id, user_name from users"):6 X( K0 B5 W+ f6 X/ C0 x( \
    2        for row in cursor:; u% F. Q# _3 _8 B
    3            print row.user_id, row.user_name
    ' j: r6 t7 P8 J6 Y/ d% U2 i* _: y" t" |  D3 n  ^& O  L* `3 U
    6)由于cursor.execute返回一个cursor,所以你可以把上面的语句简化成:& k4 l+ k& N) d6 ]
    1        for row in cursor.execute("select user_id, user_name from users"):
    : ?; I+ {& X; E' ^) x8 D, P  p( {2            print row.user_id, row.user_name
      G* O- }6 g- p0 D* K# `8 r& u0 j& h! O; d
    7)有很多SQL语句用单行来写并不是很方便,所以你也可以使用三引号的字符串来写:+ z) ~! {/ `  o
    1        cursor.execute("""1 p9 p& c, B; G* _
    2                       select user_id, user_name
    0 O" L; [# ^. Q. ^3 Q- q3                         from users" ?5 l  h8 I1 i+ t4 t% V2 V
    4                        where last_logon < '2001-01-01'& `6 I: x0 H( z  t# Y2 H; v- i
    5                          and bill_overdue = 'y': E- g7 ~- l: |" U8 J: m6 R
    6                       """)' r& B- x. Z$ m# ~& X" j
    2 [; @4 ~- [6 K& G
    3、参数
    * K! J0 X, u( i, {$ t" k9 V6 {5 \/ Y+ u1 e% N
    1)ODBC支持在SQL语句中使用一个问号来作为参数。你可以在SQL语句后面加上值,用来传递给SQL语句中的问号。- ?' I% W' ~" o! f' R! G7 K9 n
    1        cursor.execute("""; }0 b" t% V1 V: e' Y$ F% C
    2                       select user_id, user_name6 q5 W1 i: c4 C
    3                         from users1 x  }3 O; u7 @# ~2 i
    4                        where last_logon < ?
    * m" j; ~0 X1 j2 v) s5                          and bill_overdue = ?4 H* U) W9 [4 F
    6                       """, '2001-01-01', 'y'), ]: I5 f: e9 p3 E- s

    * R9 t2 @, k1 F: F4 S) M2 f& F这样做比直接把值写在SQL语句中更加安全,这是因为每个参数传递给数据库都是单独进行的。如果你使用不同的参数而运行同样的SQL语句,这样做也更加效率。
    7 g5 s" m7 L8 z: ], t% k' w3 Z
    8 V) x( H3 Y4 i5 P: u1 D" L  @3)python DB API明确说明多参数时可以使用一个序列来传递。pyodbc同样支持:( Q1 I8 \, i; _0 F
    1        cursor.execute("""
    + k+ N. m# |$ H( c6 t) Y2                       select user_id, user_name3 F% Y, }* a7 f6 K2 |& j
    3                         from users
    7 s: w" H" ?' [$ P8 u2 e4                        where last_logon < ?
    0 `! x8 V+ _5 V- Y" {5                          and bill_overdue = ?1 S" e* D. z" O/ [; V# W
    6                       """, ['2001-01-01', 'y'])
    & f4 C/ c  o" j7 l1 x
    0 F& e: Q+ \4 O1        cursor.execute("select count(*) as user_count from users where age > ?", 21)
    ! X  o9 u0 u4 H" T2        row = cursor.fetchone()
    ; ]9 M2 E2 W0 F3 ^: O3        print '%d users' % row.user_count) o5 P( F( b$ K, g
    4 R9 f9 E; u; T9 Z/ [/ H4 B
    0 }4 _& C7 @  }4 z
    % g$ d( V  `' _% U
    4、数据插入  e; R& I% y5 H6 L0 U; @

    $ k' b$ R& H+ k1 b+ F1)数据插入,把SQL插入语句传递给cursor的execute函数,可以伴随任何需要的参数。4 T' ?/ k0 B, b* Z
    1        cursor.execute("insert into products(id, name) values ('pyodbc', 'awesome library')")
    ( |+ ^( E$ q# M) P8 C2        cnxn.commit(): l8 F( E' Q# ^, W1 q  w+ D
    + c! `+ L0 `& V+ p. U, U( f+ m
    1        cursor.execute("insert into products(id, name) values (?, ?)", 'pyodbc', 'awesome library')
    " u+ B7 U% x# D" c8 A2 R& L9 R2        cnxn.commit()& ^& C. i8 Y9 Y: ?: u3 @9 h1 C
    * b' Q4 w8 T, I9 s2 T: ~/ ~
    注意调用cnxn.commit()函数:你必须调用commit函数,否者你对数据库的所有操作将会失效!当断开连接时,所有悬挂的修改将会被重置。这很容易导致出错,所以你必须记得调用commit函数。4 \- {) P+ _, u% B3 U% j
    ) j& \) {# n: o$ R6 c: @' H
    5、数据修改和删除3 e5 O5 C- h" I8 t* k4 k
    * e) ~# m8 u  B& H
    1)数据修改和删除也是跟上面的操作一样,把SQL语句传递给execute函数。但是我们常常想知道数据修改和删除时,到底影响了多少条记录,这个时候你可以使用cursor.rowcount的返回值。
    % y" X6 G) m+ a% Z6 S; _1        cursor.execute("delete from products where id <> ?", 'pyodbc')  @/ E5 [5 c% t: j
    2        print cursor.rowcount, 'products deleted'
    ) \$ d4 E1 a, ^+ Z6 N3        cnxn.commit()
    * z3 u( j+ L' o" `' v8 w( Z7 F9 v, m8 @( V$ E
    2)由于execute函数总是返回cursor,所以有时候你也可以看到像这样的语句:(注意rowcount放在最后面)1 a: X2 m6 }7 l, e, L( ]1 e  q
    1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
    - E  f1 N2 ~8 j% L6 p+ a; z  j0 P2        cnxn.commit()
    1 h4 c# X$ S4 @; @( t' v
    6 A/ r* C, b5 g7 e同样要注意调用cnxn.commit()函数
    2 e0 Z* |# i2 t3 q; r0 s$ [
    % Q4 ~5 Z- x  y- r& |, k" P* j6、小窍门
    % y  ?1 ~4 i' y5 Y8 B1 s' M0 B! ~
    5 u& e# Q5 M9 _: O5 k) G1)由于使用单引号的SQL语句是有效的,那么双引号也同样是有效的:2 w9 ?/ s5 D2 e5 M8 y3 \
    1        deleted = cursor.execute("delete from products where id <> 'pyodbc'").rowcount
    6 y- Q: @3 q5 k& B2 b" C6 E6 G$ a/ n+ @5 h
    2)假如你使用的是三引号,那么你也可以这样使用:
      l' d+ D* o- K2 H  j1        deleted = cursor.execute("""( O0 D% l. X6 X/ L
    2                                 delete3 S0 p( K0 M1 B
    3                                   from products
    3 e7 F; p' N, x5 h2 x4                                  where id <> 'pyodbc'$ z; f1 R* R1 b5 q1 k  {% j% D
    5                                 """).rowcount; q6 J( [/ Y) x
    , r" X1 `9 j3 A2 z3 i6 B& \; I" Q
    3)有些数据库(比如SQL Server)在计数时并没有产生列名,这种情况下,你想访问数据就必须使用下标。当然你也可以使用“as”关键字来取个列名(下面SQL语句的“as name-count”)
    6 y2 u/ f, o& @$ L$ b0 w) D1        row = cursor.execute("select count(*) as user_count from users").fetchone()
    # v  a: m3 ~, y7 o2        print '%s users' % row.user_count- d# d$ A4 H3 ~4 l7 m5 o
    9 ?: G# G, S, X+ S0 K4 ]
    4)假如你只是需要一个值,那么你可以在同一个行局中使用fetch函数来获取行和第一个列的所有数据。
    , x. @( M" B% z0 ]; Z% @6 x1        count = cursor.execute("select count(*) from users").fetchone()[0]
    , j9 q) }3 S, e# l+ f+ Q" ^2        print '%s users' % count( _, P" ]; b4 ?! S
    1 h/ z. L' P) W* l  t
    如果列为空,将会导致该语句不能运行。fetchone()函数返回None,而你将会获取一个错误:NoneType不支持下标。如果有一个默认值,你能常常使用ISNULL,或者在SQL数据库直接合并NULLs来覆盖掉默认值。
    6 W# x5 K0 [' p; }) r5 c1        maxid = cursor.execute("select coalesce(max(id), 0) from users").fetchone()[0]8 X' r8 D  @" \/ {. X

    ; w& f  t, x4 V; q在这个例子里面,如果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 14:43 , Processed in 0.332614 second(s), 49 queries .

    回顶部