【问题标题】:How to parameterize pyodbc identifiers in queries safely?如何安全地在查询中参数化 pyodbc 标识符?
【发布时间】:2020-02-18 08:15:43
【问题描述】:

我编写了一个小工具,可以将数据从 SQL Server 迁移到 Postgres。

为了使事情顺利进行,我使用字符串 concat 快速而肮脏地完成了它,因为我有很多其他问题要解决,而且当时我不想打扰 SQL。不过既然事情都搞定了,我想好好在SQL部门做点事情。

不安全的快速和肮脏的版本:

import pyodbc
# this is the bad example DON'T do this
    def getDataFromTable(self,table):
        """
        Gets all data from the specified Table.
        table -- Table name as string
        """
        cursor = self.cursor
        SQL = f"""SELECT * FROM {table}""" ## DON'T do this
        cursor.execute(SQL)
        rows = cursor.fetchall()
        records = []
        for row in rows:
            records.append(list(row))
        return records

这工作得很好,但是等待发生的 SQL 注入。

我想构建这样的东西(我省略了未更改的部分):

...
cursor = self.cursor
SQL = f"""SELECT * FROM ?""" # Use parameters insted of string concats
cursor.execute(SQL, table) # pass parameters to the execute method.
rows = cursor.fetchall()
...

这看起来不错的保险箱,但也不起作用。弹出以下错误:

pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Die @P1-Tabellenvariable muss deklariert werden. (1087) (SQLExecDirectW); [42000] [Microsoft ][ODBC SQL Server 驱动程序][SQL Server]Anweisung(en) konnte(n) nicht vorbereitet werden. (8180)')

它是德语,但大致翻译为:必须声明表变量,无法准备语句。

如何将变量传递给执行方法以安全地放置标识符?

【问题讨论】:

    标签: python sql sql-server pyodbc


    【解决方案1】:

    SQL Server 中的表名不能有变量。你可以在python中生成一个字符串,然后执行。

    table_name = 'table1' 
    query = "Select * from %s" % table_name
    

    或者你可以使用Dynamic SQL

    【讨论】:

    • 嘿,谢谢,我已经尝试过了,但它也不起作用,但错误已更改:pyodbc.ProgrammingError: ('SQL 包含 0 个参数标记,但提供了 1 个参数' , 'HY000')
    猜你喜欢
    • 1970-01-01
    • 2013-05-14
    • 2017-03-14
    • 2016-10-24
    • 2022-06-15
    • 1970-01-01
    • 2023-02-17
    • 1970-01-01
    • 2013-01-02
    相关资源
    最近更新 更多