我有一个使用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)
它不起作用。这次的错误是:qazxsw poi。
我正在寻找任何溶剂,所以我将能够以任何两种方式运行它。性能方面也很重要 - 应用程序不经常运行,但每次代码部分都会向pyodbc.Error: ('HY000', '[HY000] [ODBC Firebird Driver][Firebird]Dynamic SQL Error\nSQL error code = -104\nToken unknown - line 1, column 5\nterm (-104) (SQLExecDirectW)')
表插入约50k。
第一个错误是由于您将files
值插入名为null
的not null
列,换句话说您的变量FILE_TYPE_ID
为null,并且列上的约束不允许这样做,或者其他内容出错。
我用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语句引起的,它是特定于客户端工具切换语句终止符的语句,另请参见set term
Execute block是一个匿名的“存储”过程,通常不用于以这种方式执行预准备语句。由于使用了字符串格式,因此使用执行块特别不安全,因为你使用了字符串格式,而且由于执行块,这种形式比执行'normal'语句更危险。
有几个用于Python,firebird procedural query throwing "token unknown" error at "SET TERM #;"和FDB的Firebird数据库驱动程序,这样您就不需要使用ODBC。