python - 仅参数作为值的 case 表达式中的数据类型未知

标签 python firebird

当我尝试执行一个简单的查询时,我在 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 部分的准备工作很好。您可能不会问我有关表的架构的信息,因为我在此查询中没有使用任何字段。因此,您可以使用任何表重现此错误。

证据

enter image description here

最佳答案

问题是 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/

相关文章:

python - 当单击表单上的其他位置时,tkinter 列表框失去了选择

python - 使用 pandas 比较两列

c# - Firebird .NET 提供商和嵌入式服务器 3

firebird - SymmetricDS 中的数据传递

java - 使用 jaybird 2.1.6 在 blob 字段中插入文件

python - 导入错误 : cannot import name UserSerializer while creating a demo rest api

python - 使用列表推导构建元组

python - 使用 Pyramid 和 python 3 进行国际化

database - Firebird 数据库的 Web 界面

Firebird-数据库文件关闭错误消息