我有一个使用pyodbc连接数据库的应用程序。它可以通过不同的数据库引擎运行。现在我尝试将它改编为Firebird。
对于某些数据库引擎(使用sqlite,Sybase测试),我可以使用本机pyodbc方式来处理绑定参数:
cnxn = pyodbc.connect(connect_string, autocommit=True)
cur = cnxn.cursor()
cur.execute("insert into files (file_type_id, path, md5) values (?, ?, ?)", file_type_id, path, md5)
对于Oracle,我必须准备一些特殊的SQL来运行:
cnxn = pyodbc.connect(connect_string, autocommit=True)
cur = cnxn.cursor()
sql = """DECLARE v_file_type_id INT; v_path varchar2(1024); v_md5 varchar2(32);
BEGIN
v_file_type_id := %d;
v_path := '%s';
v_md5 := '%s';
insert into files (file_type_id, path, md5) values (v_file_type_id, v_path, v_md5);
END;""" % (file_type_id, path, md5)
cur.execute(sql)
第一种方式不适用于Firebird。我收到错误:pyodbc.IntegrityError: ('23000', '[23000] [ODBC Firebird Driver][Firebird]validation error for column FILE_TYPE_ID, value "*** null ***" (-625) (SQLExecDirectW)')
。
我尝试准备专用SQL,就像Oracle一样,但我遇到了一些问题。
cnxn = pyodbc.connect(connect_string, autocommit=True)
cur = cnxn.cursor()
sql = """set term ^ ;
execute block
as
declare v_file_type_id int = %d;
declare v_path varchar(1024) = '%s';
declare v_md5 varchar(32) = '%s';
begin
insert into files (file_type_id, path, md5) values (:v_file_type_id, :v_path, :v_md5);
end
^
set term ; ^""" % (file_type_id, path, md5)
cur.execute(sql)
它不起作用。这次的恐怖是:pyodbc.Error: ('HY000', '[HY000] [ODBC Firebird Driver][Firebird]Dynamic SQL Error\nSQL error code = -104\nToken unknown - line 1, column 5\nterm (-104) (SQLExecDirectW)')
。
我正在寻找任何溶剂,所以我将能够以这两种方式运行它。性能方面也非常重要 - 应用程序不经常运行,但每次代码部分对files
表进行大约50k的插入时。
答案 0 :(得分:2)
第一个错误是由于您将null
值插入名为not null
的{{1}}列,换句话说您的变量FILE_TYPE_ID
为空,并且列上的约束不允许这样做,或者其他东西出错。
我用Python或其DB-API做了一段时间,但据我记忆,你执行的方式是错误的:
file_type_id
应该(注意使用元组)
cur.execute("insert into files (file_type_id, path, md5) values (?, ?, ?)", file_type_id, path, md5)
第二个错误是由cur.execute("insert into files (file_type_id, path, md5) values (?, ?, ?)", (file_type_id, path, md5))
不是有效的Firebird SQL语句引起的,它是特定于客户端工具切换语句终止符的语句,另请参阅firebird procedural query throwing "token unknown" error at "SET TERM #;"
执行块是一个匿名的“存储”过程,通常不用于以这种方式执行预准备语句。由于使用了字符串格式,因此使用执行块特别不安全,因为你使用了字符串格式,而且由于执行块这个形式比执行'normal'语句更危险。
Python有几个Firebird数据库驱动程序,FDB和pyfirebirdsql,这样您就不需要使用ODBC。