cx_Oracle.DatabaseError: ORA-00932: 不一致的数据类型:预期的 CHAR 得到 NUMBER

时间:2021-03-25 13:30:59

标签: python sql python-3.x oracle

我正在尝试将 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 行上。

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

1 个答案:

答案 0 :(得分:0)

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)
相关问题