根据你描述的情况以及调试截图中的内容,我可以确认你的 sql
字符串在 Python 中由于转义字符的问题,可能导致在 Oracle 中运行时出错。
以下是一些排查和修改建议:
问题分析
-
转义字符问题:
- 在调试界面中可以看到,
DECODE(c.bin_flag, 1, '\\Pass\\', '\\Fail\\')
中多余的\\
是 Python 中的转义字符,可能在实际执行 SQL 时未被正确解析。 - 在 Python 中,字符串中的
\
本身需要通过\\
表示,但在 SQL 中不需要这种转义。
- 在调试界面中可以看到,
-
ORA-00911 错误:
- Oracle 的 ORA-00911 通常指的是 SQL 语法问题,例如非法字符或未正确转义的符号。
- 你当前 SQL 语句的拼接部分可能未正确处理这种问题,尤其是在
DECODE
和REGEXP_REPLACE
中的字符串内容。
修复建议
方法 1:使用原始字符串 r''
你可以将 SQL 中的字符串用 Python 的原始字符串方式表示,避免手动转义符号。改写如下:
python
sql = r"""SELECT a.*, b.bin_code, b.merge_count, b.first_count, b.rt_count,
DECODE(c.bin_flag, 1, 'Pass', 'Fail') P_F ,
REGEXP_REPLACE(ROUND(b.merge_count / die_tested * 100, 2), '^\.', '0.') || '%' Percent
FROM (SELECT a.* FROM (SELECT t.*, ROW_NUMBER() OVER(PARTITION BY t.lot_id ORDER BY t.eda_load_time DESC) rn
FROM SJTYS.ft_rawdata t WHERE t.lot_id = :lotid AND t.step LIKE 'ST%') a WHERE a.rn = 1) a
LEFT JOIN SJTYS.ft_rawdata_bin_sum b ON a.id = b.id AND b.bin_type = 'H'
LEFT JOIN SJTYS.ft_bdf_definition c ON a.bdf_file_name = c.bdf_file_name
AND b.bin_code = c.bin_code AND b.bin_type = c.bin_type
WHERE DECODE(c.bin_flag, 1, 'Pass', 'Fail') = 'Pass' ORDER BY b.bin_code"""
这里的改进:
- 使用了原始字符串
r"""..."""
,避免手动转义引入的问题。 - 用
:lotid
替代了直接拼接lotid
的方式(推荐使用参数化查询)。
方法 2:参数化查询
直接拼接字符串容易导致 SQL 注入风险。推荐使用参数化查询:
python
def Query_Info_First(prodid, lotid):
connection = cx_Oracle.connect("user", "uerpwd", "ip:port/service")
cursor = connection.cursor()
sql = """SELECT a.*, b.bin_code, b.merge_count, b.first_count, b.rt_count,
DECODE(c.bin_flag, 1, 'Pass', 'Fail') P_F ,
REGEXP_REPLACE(ROUND(b.merge_count / die_tested * 100, 2), '^\.', '0.') || '%' Percent
FROM (SELECT a.* FROM (SELECT t.*, ROW_NUMBER() OVER(PARTITION BY t.lot_id ORDER BY t.eda_load_time DESC) rn
FROM SJTYS.ft_rawdata t WHERE t.lot_id = :lotid AND t.step LIKE 'ST%') a WHERE a.rn = 1) a
LEFT JOIN SJTYS.ft_rawdata_bin_sum b ON a.id = b.id AND b.bin_type = 'H'
LEFT JOIN SJTYS.ft_bdf_definition c ON a.bdf_file_name = c.bdf_file_name
AND b.bin_code = c.bin_code AND b.bin_type = c.bin_type
WHERE DECODE(c.bin_flag, 1, 'Pass', 'Fail') = 'Pass' ORDER BY b.bin_code"""
cursor.execute(sql, lotid=lotid)
MultiTable_INFO = cursor.fetchall()
cursor.close()
connection.close()
return MultiTable_INFO
方法验证
建议你按照以下步骤调试:
- 将上面的方法替换到你的代码中,优先使用 方法 2(参数化查询)。
- 检查是否仍有 ORA-00911 报错。如果仍有问题:
- 打印
sql
字符串的最终值,确保语句和 Oracle 中运行的语句完全一致。 - 手动在 Oracle 中再次运行以验证语法是否正确。
- 打印
常见注意事项
-
转义字符问题:
- 避免在 SQL 中直接使用 Python 的
\
转义字符,建议使用单引号''
或原始字符串。
- 避免在 SQL 中直接使用 Python 的
-
字符串拼接:
- SQL 语句中直接拼接变量容易导致语法错误,使用参数化查询可以避免此类问题。
-
Oracle 函数和字段名:
- 确保 SQL 中使用的字段名、表名等正确无误,尤其是别名、函数(如
REGEXP_REPLACE
)是否支持。
- 确保 SQL 中使用的字段名、表名等正确无误,尤其是别名、函数(如
请根据我的建议调整后测试!如果仍有问题,可以进一步提供更多信息。