使用连接到 Firebird 的 pyodbc 绑定参数
Binding parameters using pyodbc with connection to Firebird
我有一个使用 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
table 插入大约 50k 次。
第一个错误是由于您将 null
值插入到名为 FILE_TYPE_ID
的 not null
列中,换句话说,您的变量 file_type_id
为空, 并且列的约束不允许这样做,或者其他地方出了问题。
我已经有一段时间没有对 Python 或其 DB-API 做任何事情了,但据我所知,你执行的方式是错误的:
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))
第二个错误是因为set term
不是有效的Firebird SQL语句,它是客户端工具切换语句终止符的特定语句,另见firebird procedural query throwing "token unknown" error at "SET TERM #;"
Execute 块是一个匿名的 'stored' 过程,通常不用于以这种方式执行准备好的语句。您对执行块的使用特别不安全,因为您使用的是字符串格式,因此您正在向 SQL 注入,并且由于执行块,这种形式比执行 'normal' 语句更危险。
Python、FDB and pyfirebirdsql 有多个 Firebird 数据库驱动程序,这样您就不需要使用 ODBC。
我有一个使用 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
table 插入大约 50k 次。
第一个错误是由于您将 null
值插入到名为 FILE_TYPE_ID
的 not null
列中,换句话说,您的变量 file_type_id
为空, 并且列的约束不允许这样做,或者其他地方出了问题。
我已经有一段时间没有对 Python 或其 DB-API 做任何事情了,但据我所知,你执行的方式是错误的:
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))
第二个错误是因为set term
不是有效的Firebird SQL语句,它是客户端工具切换语句终止符的特定语句,另见firebird procedural query throwing "token unknown" error at "SET TERM #;"
Execute 块是一个匿名的 'stored' 过程,通常不用于以这种方式执行准备好的语句。您对执行块的使用特别不安全,因为您使用的是字符串格式,因此您正在向 SQL 注入,并且由于执行块,这种形式比执行 'normal' 语句更危险。
Python、FDB and pyfirebirdsql 有多个 Firebird 数据库驱动程序,这样您就不需要使用 ODBC。