【问题标题】:cx_Oracle.DatabaseError: ORA-00932: inconsistent datatypes: expected CHAR got NUMBERcx_Oracle.DatabaseError:ORA-00932:不一致的数据类型:预期的 CHAR 得到了 NUMBER
【发布时间】:2021-06-22 07:33:28
【问题描述】:

我正在尝试将 Python 中的用户输入传递到 SQL 以按日期范围过滤数据。我在 SQL 中没有遇到任何问题,例如:

SELECT * from trades
WHERE share_id = 1
AND broker_id =1
AND transaction_time >= TO_DATE('2020-11-01','YYYY-MM-DD')
AND transaction_time <= TO_DATE('2020-12-01','YYYY-MM-DD');

我在 Python 中也没有遇到问题,只有 transaction_time 部分,例如:

from_date_val = input("Enter from-date (YYYY-MM-DD) to search, enter nothing to skip: ")
to_date_val = input("Enter to-date (YYYY-MM-DD) to search, enter nothing to skip: ")

cursor.execute("""SELECT * FROM trades WHERE 1=1
                  AND transaction_time >= CASE WHEN :from_date IS NOT NULL
                  THEN TO_DATE(:from_date, 'YYYY-MM-DD') 
                  ELSE transaction_time END
                  AND transaction_time <= CASE WHEN :to_date IS NOT NULL
                  THEN TO_DATE(:to_date, 'YYYY-MM-DD') 
                  ELSE transaction_time END""", 
                  from_date = from_date_val, 
                  to_date = to_date_val)

但如果我这样做:

share_id_val = input("Enter share id to search, enter nothing to skip: ")
broker_id_val = input("Enter broker id to search, enter nothing to skip: ")
from_date_val = input("Enter from-date (YYYY-MM-DD) to search, enter nothing to skip: ")
to_date_val = input("Enter to-date (YYYY-MM-DD) to search, enter nothing to skip: ")

cursor.execute("""SELECT * FROM trades WHERE 1=1
                  AND share_id = CASE WHEN :share_id IS NOT NULL 
                  THEN :share_id ELSE share_id END
                  AND broker_id = CASE WHEN :broker_id IS NOT NULL 
                  THEN :broker_id ELSE broker_id END
                  AND transaction_time >= CASE WHEN :from_date IS NOT NULL
                  THEN TO_DATE(:from_date, 'YYYY-MM-DD') 
                  ELSE transaction_time END
                  AND transaction_time <= CASE WHEN :to_date IS NOT NULL
                  THEN TO_DATE(:to_date, 'YYYY-MM-DD') 
                  ELSE transaction_time END""", 
                  share_id = share_id_val, 
                  broker_id = broker_id_val,
                  from_date = from_date_val, 
                  to_date = to_date_val)

它返回:cx_Oracle.DatabaseError:

ORA-00932:不一致的数据类型:预期的 CHAR 得到了 NUMBER。

from_date = from_date_valto_date = to_date_val 的行上。

这真的让我发疯了几个小时,有人可以帮我解决这个问题吗?提前致谢。

【问题讨论】:

  • 你确定是from_date = from_date_valto_date = to_date_val吗?您是否尝试过在:share_id:broker_id 上使用TO_NUMBER?或者将这些 python 值从字符串转换为 int,然后再将它们传递给绑定变量?
  • 这能回答你的问题吗? Oracle SQL CASE WHEN ORA-00932: inconsistent datatypes: expected CHAR got NUMBER 00932. 00000 - "inconsistent datatypes: expected %s got %s"。很明显,问题出在您的CASE 语句中,带有share_idbroker_id。因为它是在添加它们之后出现的。
  • 谢谢@MT0 成功了!!错误消息一直告诉我这是日期的概率,我从没想过这些 id 可能有问题。
  • 谢谢@astentx 成功了!!错误消息一直告诉我这是日期的概率,我从没想过这些 id 可能有问题。

标签: python sql python-3.x oracle


【解决方案1】:

share_idbroker_idNUMBER 数据类型;但是,在 Python 中,input 函数返回一个字符串,您将其直接作为绑定变量传递,然后:

CASE WHEN :share_id IS NOT NULL THEN :share_id ELSE share_id END

:share_id 绑定变量将是字符串数据类型,share_id 列具有NUMBER 数据类型;这会导致您的错误:

ORA-00932: inconsistent datatypes: expected CHAR got NUMBER.

要修复它,您需要将字符串输入值转换为数字。您可以在 Python 中使用int() 进行转换:

cursor.execute("""SELECT * FROM trades WHERE 1=1
                  AND share_id = CASE WHEN :share_id IS NOT NULL 
                  THEN :share_id ELSE share_id END
                  AND broker_id = CASE WHEN :broker_id IS NOT NULL 
                  THEN :broker_id ELSE broker_id END
                  AND transaction_time >= CASE WHEN :from_date IS NOT NULL
                  THEN TO_DATE(:from_date, 'YYYY-MM-DD') 
                  ELSE transaction_time END
                  AND transaction_time <= CASE WHEN :to_date IS NOT NULL
                  THEN TO_DATE(:to_date, 'YYYY-MM-DD') 
                  ELSE transaction_time END""", 
                  share_id = int(share_id_val), 
                  broker_id = int(broker_id_val),
                  from_date = from_date_val, 
                  to_date = to_date_val)

或者在SQL语句中使用TO_NUMBER

cursor.execute("""SELECT * FROM trades WHERE 1=1
                  AND share_id = CASE WHEN :share_id IS NOT NULL 
                  THEN TO_NUMBER(:share_id) ELSE share_id END
                  AND broker_id = CASE WHEN :broker_id IS NOT NULL 
                  THEN TO_NUMBER(:broker_id) ELSE broker_id END
                  AND transaction_time >= CASE WHEN :from_date IS NOT NULL
                  THEN TO_DATE(:from_date, 'YYYY-MM-DD') 
                  ELSE transaction_time END
                  AND transaction_time <= CASE WHEN :to_date IS NOT NULL
                  THEN TO_DATE(:to_date, 'YYYY-MM-DD') 
                  ELSE transaction_time END""", 
                  share_id = share_id_val, 
                  broker_id = broker_id_val,
                  from_date = from_date_val, 
                  to_date = to_date_val)

【讨论】:

  • 非常感谢 :) 效果很好。
猜你喜欢
  • 2014-12-28
  • 1970-01-01
  • 2013-05-31
  • 2019-07-24
  • 1970-01-01
  • 2016-07-09
  • 2014-06-06
  • 2017-12-28
  • 1970-01-01
相关资源
最近更新 更多