oracle Python脚本中的多个占位符SQL不工作[重复]

bzzcjhmw  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(89)

此问题已在此处有答案

How to use variables in SQL statement in Python?(6个回答)
上个月关门了。
我尝试在SQL查询中插入两个日期,但脚本显示以下错误:Oracle数据库中存在错误:ORA-01036:非法变量名称/编号 *

starting_date='01/01/2023'
ending_date='01/04/2023'

params = (starting_date,ending_date)
cur.execute('SELECT analisi.codice, analisi.descrizione FROM analisi LEFT JOIN ris ON analisi.codice = ris.analisi LEFT JOIN ric ON ris.richiesta_id = ric.richiesta_id WHERE ric.richiesta_ins_data >= TO_DATE(?, \'dd/mm/yyyy\')         AND ric.richiesta_ins_data <= TO_DATE(?, \'dd/mm/yyyy\') AND ris01 IS NOT NULL AND ris01 NOT IN (\'N01\',\'N10\') GROUP BY analisi.codice, analisi.descrizione', params)

我试过只用一个占位符,它的工作原理

sql = "SELECT analisi.codice, analisi.descrizione FROM analisi LEFT JOIN  ris ON analisi.codice = ris.analisi LEFT JOIN ric ON ris.richiesta_id = ric.richiesta_id WHERE ric.richiesta_ins_data >= TO_DATE('%s', \'dd/mm/yyyy\')         AND ric.richiesta_ins_data <= TO_DATE(\'31/03/2023\', \'dd/mm/yyyy\') AND ris01 IS NOT NULL AND ris01 NOT IN (\'N01\',\'N10\') GROUP BY analisi.codice, analisi.descrizione" %starting_date
        
        # cur.execute(sql)

我做错了什么?

fumotvh3

fumotvh31#

这个问题是使用字符串连接和插值放在首位,并不能修复任何数量的报价或净化。这就允许SQL注入攻击和转换错误,就像我们仍然在新闻中看到的那样,关于由于“计算机错误”而导致的巨额账单。那是4月1日还是1月4日?为什么有人要假设这两个日期?
一个更好、实际上更容易的选择是使用查询参数。在这种情况下,参数值永远不会转换为文本,也永远不会成为查询的一部分,甚至不会成为执行计划的一部分。这些值将不作更改地传递到数据库。数据库将查询编译为带有 * 参数的执行计划,并使用查询参数的值执行它。
在Oracle中,查询参数称为Bind Variables,可以通过名称或位置传递。使用它们会产生更干净,而不仅仅是更安全的代码:

sql = """insert into departments (department_id, department_name)
         values (:dept_id, :dept_name)"""
cursor.execute(sql, [280, "Facility"])

问题的代码可以更改为:

from datetime import date

sql=""" 
    SELECT analisi.codice, analisi.descrizione 
    FROM analisi LEFT JOIN ris ON analisi.codice = ris.analisi 
    LEFT JOIN ric ON ris.richiesta_id = ric.richiesta_id 
    WHERE ric.richiesta_ins_data >= :ins_start 
      AND ric.richiesta_ins_data <= :ins_end
      AND ris01 IS NOT NULL 
      AND ris01 NOT IN (:ris1,:ris2) 
    GROUP BY analisi.codice, analisi.descrizione
    """

starting_date=date(2023,1,1)
ending_date=date(2023,4,1)
ris1='N01'
ris2='N10'

cur.execute(sql,[starting_date,ending_date,ris1,ris2])

相关问题