【发布时间】:2016-05-14 16:48:09
【问题描述】:
我有一个查询,当我在 sqlplus 中运行它时效果很好:
SQL> SELECT T_0.ID AS ATTR_1_, T_0_0.ID AS ATTR_2_,
CASE WHEN ( T_0.ID=1 AND ( T_0_0.ID=3 OR T_0_1.ID='val_1') )
THEN 'val_1' ELSE 'val_2' END AS TXT, T_0_1.ID,
CASE WHEN T_0.ID='boo' THEN 'boo' END AS EXTRA_FIELD
FROM TEST_TABLE T_0
INNER JOIN TEST_TABLE_2 T_0_0 ON ( T_0_0.ATTR=T_0.ID )
INNER JOIN TEST_TABLE_3 T_0_1 ON ( T_0_1.ID = T_0_0.ID )
WHERE ( ( T_0.ID=1 AND T_0_0.ID=3 )
OR T_0_1.ID=2 OR T_0_0.TXT='val_2');
no rows selected
虽然它什么也不返回,但它仍然有效并且不会导致错误。但是,当我在 Python 中使用绑定做同样的事情时,我会收到以下错误消息:
cx_Oracle.DatabaseError: ORA-01722: invalid number
这是我的查询在 Python 中的样子,在我执行 cursor.execute 之前:
SELECT T_0.ID AS ATTR_1_, T_0_0.ID AS ATTR_2_,
CASE WHEN ( T_0.ID=:TXT_ AND ( T_0_0.ID=:TXT__ OR T_0_1.ID=:TXT___ ) )
THEN :TXT___ ELSE :TXT____ END AS TXT, T_0_1.ID,
CASE WHEN T_0.ID=:EXTRA_FIELD THEN :EXTRA_FIELD END AS EXTRA_FIELD
FROM TEST_TABLE T_0
INNER JOIN TEST_TABLE_2 T_0_0 ON ( T_0_0.ATTR=T_0.ID )
INNER JOIN TEST_TABLE_3 T_0_1 ON ( T_0_1.ID = T_0_0.ID )
WHERE ( ( T_0.ID=:ID AND T_0_0.ID=:ID_ )
OR T_0_1.ID=:ID__ OR T_0_0.TXT=:TXT )
查询只是一个用双引号引起来的字符串 "SELECT ..." 。这就是带有绑定变量的字典的样子:
OrderedDict([('TXT_', 1), ('TXT__', 3), ('TXT___', 'val_1'),
('TXT____', 'val_2'), ('EXTRA_FIELD', 'boo'), ('ID', 1),
('ID_', 3), ('ID__', 2), ('TXT', 'val_2')])
所以,如您所见,我有一个完美的字典 - 数值只是不带引号的数字,字符串值只是带单引号的字符串。我知道,您会询问表的架构。所以,这里是:
SQL> SELECT COLUMN_NAME, DATA_TYPE FROM USER_TAB_COLUMNS WHERE
TABLE_NAME = 'TEST_TABLE';
COLUMN_NAME
------------------------------
DATA_TYPE
------------------------------
ID
NUMBER
SQL> SELECT COLUMN_NAME, DATA_TYPE FROM USER_TAB_COLUMNS WHERE
TABLE_NAME = 'TEST_TABLE_2';
COLUMN_NAME
------------------------------
DATA_TYPE
------------------------------
ATTR
NUMBER
ID
NUMBER
TXT
VARCHAR2
SQL> SELECT COLUMN_NAME, DATA_TYPE FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'TEST_TABLE_3';
COLUMN_NAME
------------------------------
DATA_TYPE
------------------------------
ID
NUMBER
因此,似乎同一个查询在控制台中运行良好,但在使用 Python 时却无法运行。这是为什么呢?
编辑
这是一个证明 - 两个控制台窗口的屏幕。在第一个控制台中,我在 sqlplus 中运行查询,在第二个控制台中,我打印 sql 查询和用于绑定变量的字典:
编辑
哦,这更有趣。我能够在 Oracle shell 中重现此错误,它看起来像 Oracle 11c 错误。所以,看看这个:
请注意ID 字段具有NUMBER 类型。然后注意这两个屏幕:
在上面的屏幕中,您可以看到一切正常。但是,如果我们通过将OR T_0_1.ID=2 添加到 WHERE 部分来稍微改变它,那么它就会中断:
所以,即使在 Oracle shell 中,这个问题也是可以重现的。你可以使用我上面提供的架构来做到这一点。
编辑
我更新了我的问题的主题,因为它与 Python 无关。 Oracle 本身的整个问题。
编辑
顺便说一句。我的最后评论与我调查的开始部分并不矛盾。问题是,如果我在 TEST_TABLE_3 中有一些数据,那么查询就会中断。如果我删除数据,那么它就开始工作了。这是一个很大的证明:
数据如何影响查询的正确性??
【问题讨论】:
-
您是否尝试缩小范围,看看问题出在哪里?比如注释掉“INNER JOIN”这两条线,重新编译试试;您仍然收到错误消息吗?这会告诉你去哪里看。
-
不,我还没试过。
-
我的查询是由自动测试之一生成的。现在我将尝试对其进行硬编码。
-
顺便说一句,我不能注释掉最后两个 JOINS,因为我在 SELECT ... 部分中使用了连接表中的字段。
-
我设法缩小了范围。整个问题仅由查询的 WHERE 部分引起。如果我将其删除并删除相应的绑定,则可以。但是我的绑定有什么问题?
标签: oracle