偶一向是使用.net的,最近想用python做一些东西,但是用python新做的这些东西,还是需要使用到原来ms
sql server
2005里面的数据......自己折腾很久,似乎还是找不到一个妥善的方案......
我已经试过adodbapi
(http://test.sf.net/projects/adodbapi/),感觉似乎bug多多......执行:
cs.execute('select 1 as t1 where 1=?', [1])
都会出莫名的错误。
本来看到从php
port过来的adodb还以为找到救星,无奈它底层居然是用mxODBC这个商业组件......一千多块美金实在太贵......
现在暂时只能使用python win自带的odbc
interface......虽然只支持DB-API spec
v1.0,但似乎勉强还可以用......
现在有几个问题:
1. 是否有比odbc interface更加高级点的免费库可以用呢?
2. 如果使用odbc
interface这个古老的东西的话,我是否可以认为因为它很简单,所以,效率应该很高?
3. 使用odbc
interface需要如何在执行存储过程的时候,获得output参数的值?
4. 因为DB-API
fetchone/all等的时候,返回的tuple是不包涵列名的,偶写了下面的小程序,大家能否帮忙提一下意见?小弟不胜感激~
import odbc
connstr="DSN=naruto;UID=sa;PWD=password"
c = odbc.odbc(connstr)
class DataRow:
ids = {}
def __init__(self, dt, description):
self.dt=dt
i = 0
if type(description) == list:
for it in description:
self.ids[it[0]] = i
i += 1
elif type(description) == dict:
self.ids = description
def __getitem__ (self, itemName):
if type(itemName) == int:
return self.dt[itemName]
else:
return self.dt[self.ids[itemName]]
class DataTable:
ids = {}
def __init__(self, dt, description):
self.dt=dt
i = 0
if type(description) == list:
for it in description:
self.ids[it[0]] = i
i += 1
elif type(description) == dict:
self.ids = description
def __getitem__ (self, itemName):
return DataRow(self.dt[itemName],self.ids)
def exeScalar(sql, parameters=None, sp=0):
if sp == 1:
sql = "exec " + sql
cs = c.cursor()
if parameters!=None:
cs.execute(sql,parameters)
else:
cs.execute(sql)
row = cs.fetchone()
cs.close()
if row == None:
return row
else:
return row[0]
def exeRow(sql, parameters=None, sp=0):
if sp == 1:
sql = "exec " + sql
cs = c.cursor()
if parameters!=None:
cs.execute(sql,parameters)
else:
cs.execute(sql)
row = cs.fetchone()
cs.close()
return DataRow(row,cs.description)
if row == None:
return None
dt = {}
i = 0
for it in cs.description:
dt[it[0]] = row[i]
dt[i] = row[i]
i += 1
return dt
def exeTable(sql, parameters=None, sp=0):
if sp == 1:
sql = "exec " + sql
cs = c.cursor()
if parameters!=None:
cs.execute(sql,parameters)
else:
cs.execute(sql)
dt = cs.fetchall()
cs.close()
return DataTable(dt,cs.description)
def exeNonQuery(sql, parameters=None, sp=0):
if sp == 1:
sql = "exec " + sql
cs = c.cursor()
if parameters!=None:
cs.execute(sql,parameters)
else:
cs.execute(sql)
cs.close()
如果实在找不到解决方法,建议使用sqlalchemy。他已经比较完善的解决了数据库连接和跨线程的问题。
另外,可以使用pymssql
http://sourceforge.net/projects/pymssql
不过这个类库是绝对的client端游标(ms说法),如果你查一个表的所有数据,而这个数据又太大,会比较痛苦。
--
张骏 <zha...@foreseen-info.com>
敏捷来自Python
简单源于我们
丰元信信息技术有限公司
Python技术交流群:22507237
呃……但是……我最初使用的adodbapi就是"用Pywin32包的COM接口调用ADO"的……
人家能开源出来应该也不是菜鸟,结果貌似还是bug多多……偶自己直接去重新发明一下轮子,恐怕更惨……
偶……最终还是用回了adodbapi……
之前偶说的错误是因为偶参数传递的方式不对……
不应该是:
cs.execute('select 1 as t1 where 1=?', [1])
而应该是
cs.execute('select 1 as t1 where 1=%d' :(1))
貌似adodbapi跟pymssql都只能使用"sql cmd" :
(parameters)的方式去传递参数。
但是,这样子相当于是在拼SQL语句……很容易被注入……异常不爽……
另外,据pymssql的官方网站(http://pymssql.sourceforge.net/)说,pymssql应该是python里面链接数据库最快的方式:
“It's the most efficient method of accessing MS SQL Server's data
from Python scripts. If you care about performance, you can give it a
try.”
pymssql似乎无法获得数据列名,反复试了几次cursor.description的值都是None……这也是偶无奈改回adodbapi的原因……不知道是否是因为偶使用方式不对,还望各位大虾指点……
pymssql还有另一个严重问题便是无法查询类型为nText的数据……按照官方网站说法:
“There's no fix for this error. A workaround is to change the column
type to NVARCHAR (it doesn't exhibit this behaviour), or plain TEXT.”
很郁闷……
另外,pymssql还是可以在*nix、OSX里面使用的,不过,我之前的说法也是没错,它需要FreeTDS做支持……
FreeTDS跟ms sql 2005似乎合不来,需要把ms sql
2005数据库的兼容模式设为7.0!才可以正常使用,貌似这相当于把ms
sql 2005当作ms sql 6.5去使用了……ms sql 2000倒是没事……
至于sqlalchemy,它的底层用的便是adodbapi或者pymssql,加多一个层而已……
(...)
另外,据pymssql的官方网站(http://pymssql.sourceforge.net/)说,pymssql应该是python里面链接数据库最快的方式:
"It's the most efficient method of accessing MS SQL Server's data
from Python scripts. If you care about performance, you can give it a
try."
pymssql似乎无法获得数据列名,反复试了几次cursor.description的值都是None……这也是偶无奈改回adodbapi的原因……不知道是否是因为偶使用方式不对,还望各位大虾指点……
pymssql还有另一个严重问题便是无法查询类型为nText的数据……按照官方网站说法:
"There's no fix for this error. A workaround is to change the column
type to NVARCHAR (it doesn't exhibit this behaviour), or plain TEXT."
很郁闷……
另外,pymssql还是可以在*nix、OSX里面使用的,不过,我之前的说法也是没错,它需要FreeTDS做支持……
FreeTDS跟ms sql 2005似乎合不来,需要把ms sql
2005数据库的兼容模式设为7.0!才可以正常使用,貌似这相当于把ms
sql 2005当作ms sql 6.5去使用了……ms sql 2000倒是没事……
你试试:
cs.execute('select 1 as t1 where 1=?', 1 )
或
cs.execute('select 1 as t1 where 1=?', ( 1 ) )
这两个我都试过,不行就是不行,莫非是偶rpwt?
嗯,windows下是可以,但是*nix下freetds无法链接sql server
2005,既便FreeTDS与sql server
2005的兼容等级都是8.0,必需都改成7.0的才可以......
传说ms sql 2005的8.0跟2000的8.0其实是不一样的......