我正在尝试将 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_val
和 to_date = to_date_val
行上。
这真的让我发疯了几个小时,有人能帮我解决这个问题吗?提前致谢。
答案 0 :(得分:0)
share_id
和 broker_id
是 NUMBER
数据类型;但是,在 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)