当我尝试执行一个简单的查询时,我在 Python 中收到此错误消息。如果我稍微改变一下这个查询,那就可以了。所以,它是这样的:
>>> import fdb
>>> cnx = fdb.connect(dsn = "C:\data\REESTR.FDB", user = "sysdba", password = "masterkey")
>>> cnx.begin()
>>> cursor = cnx.cursor()
>>> query = "SELECT CASE WHEN 'val_1' = 'val_1' THEN ? ELSE 'val_2' END AS TXT FROM TEST_TABLE"
>>> dat = ('val_1', )
>>> cursor.execute(query, dat) # this query works ok
<fdb.fbcore.Cursor object at 0x0000000002FEC978>
>>> # now let's change the query a liitle bit:
>>> query = "SELECT CASE WHEN 'val_1' = 'val_1' THEN ? ELSE ? END AS TXT FROM TEST_TABLE"
>>> dat = ('val_1', 'val_2', )
>>> cursor.execute(query, dat)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python34\lib\site-packages\fdb-1.6-py3.4.egg\fdb\fbcore.py", line 3573, in execute
self._ps = PreparedStatement(operation, self, True)
File "C:\Python34\lib\site-packages\fdb-1.6-py3.4.egg\fdb\fbcore.py", line 2182, in __init__
"Error while preparing SQL statement:")
fdb.fbcore.DatabaseError: ('Error while preparing SQL statement:\n- SQLCODE: -804\n-
Dynamic SQL Error\n- SQL error code = -804\n-
Data type unknown', -804, 335544569)
因此,如您所见,我只为查询的 ELSE 部分添加了一个额外的准备变量。这一切看起来很奇怪,因为 THEN
部分的准备工作很好。您可能不会问我有关表的架构的信息,因为我在此查询中没有使用任何字段。因此,您可以使用任何表重现此错误。
证据
最佳答案
问题是 Firebird 需要知道参数(以及结果表达式)的数据类型。它有多种策略可以做到这一点,因此
CASE WHEN 'val_1' = 'val_1' THEN ? ELSE 'val_2' END
它根据 ELSE 'val_2'
将 CASE 表达式的类型推断为 CHAR(4)
,因此 THEN ?
中的参数code> 也是一个 CHAR(4)
。
但是当出现
CASE WHEN 'val_1' = 'val_1' THEN ? ELSE ? END
它没有信息来推断参数的类型或整个 CASE
表达式的类型。例如,如果这是一个 WHERE
子句,它可以根据与表达式进行比较的列来推断它。
为了帮助 Firebird,您需要通过将一个(或两个)参数显式转换为正确的类型来给出提示(这适用于 Firebird 2.5 及更高版本):
CASE WHEN 'val_1' = 'val_1' THEN CAST(? AS CHAR(4)) ELSE ? END
我相信(但没有测试)在较旧的 Firebird 版本中您可能可以使用类似的东西
CASE WHEN 'x' <> 'x' THEN 'DUMMY' WHEN 'val_1' = 'val_1' THEN ? ELSE ? END
使其成为CHAR(5)
。
关于python - 仅参数作为值的 case 表达式中的数据类型未知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37348807/