使用 Python 和 mySQL 进行动态 SQL 查询

Posted

技术标签:

【中文标题】使用 Python 和 mySQL 进行动态 SQL 查询【英文标题】:Dynamic SQL Queries with Python and mySQL 【发布时间】:2021-09-20 19:20:45 【问题描述】:

我有多个表在网格中的值更改后更新。这些表并不总是具有相同的键或列,因此我无法明确命名列或格式。唯一相同的是键所在的列。我知道我目前这样做的方式是不正确的,这让我很容易受到注入攻击。

我还遇到了一个问题,其中一些值包含在 SQL 语句中引发错误的键。比如更新WHERE email = t'est@email.com

我不太确定编写这些语句的正确方法。我做了一些研究,看到了多种用于不同目的的方法,但不确定哪种方法合适。我希望尽可能动态地执行此操作。谁能指出我正确的方向?

连接:

import mysql.connector as sql
import MySQLdb

#Connect
self.db_name = 'database'
        self.server = 'server'
        self.user_id = 'user'
        self.pw = 'password'

        try:
            self.db_con = MySQLdb.connect(user=self.user_id,password=self.pw,database=self.db_name,
                                    host=self.server,charset='utf8',autocommit=True)
            self.cursor = self.db_con.cursor()
        except:
            print("Error connecting")    

SQL 语句:

key_id =  str("'") + self.GetCellValue(event.GetRow(),1) +  str("'")    
        target_col = self.GetColLabelValue(event.GetCol())
        key_col = self.GetColLabelValue(1)                                     
        nVal = str("'") + self.GetCellValue(event.GetRow(),event.GetCol()) +  str("'")

#SQL STATEMENTS
        sql_update = "UPDATE " + tbl + " SET " +  target_col + " = " + nVal + " WHERE " + key_col  +  " = " + key_id + ""
        

#INSERT
        sql_update = ("INSERT INTO " + str(self.tbl) + "(" + self.key_col + ")" + "VALUES (" + str("'") + str(val) + str("'") + ")")

#DELETE
        sql_update = "DELETE FROM " + tbl + " WHERE " + self.key_col + " = " + self.key_id + ""

#SELECT
        sql_query = "SELECT * FROM " + self.tbl 

#Excecute
        try:
            self.cursor.execute(sql_update)
            
            
        except:
            print('Error')
            self.db_con.rollback()

【问题讨论】:

你从哪里得到查询的值,你有任何前端吗? 值数据库和服务器在我的代码中是明确的。用户和密码在用户登录时确定。Tbl 由组合框中的选择确定。 Target_col、key_col、key_id 和 nVal 是从 wxgrid 表中提取的 【参考方案1】:

数据库对于“引用”identifiers(表和列名等)和(数据)有不同的表示法。

MySQL 使用 反引号 来引用标识符。对于值,最好使用连接器包提供的参数替换机制:它更有可能正确处理嵌入引号等棘手的情况,并且会降低 SQL 注入的风险。

这是一个插入示例;相同的技术可用于其他类型的查询。

key_id =  str("'") + self.GetCellValue(event.GetRow(),1) +  str("'")    
target_col = self.GetColLabelValue(event.GetCol())
key_col = self.GetColLabelValue(1)                                     
nVal = str("'") + self.GetCellValue(event.GetRow(),event.GetCol()) +  str("'")
        

#INSERT (using f-strings for brevity)
sql_update = (f"INSERT INTO `self.tbl` (`self.key_col`) VALUES (%s)")

# Pass the statement and values to cursor.execute.  
# The values are assumed to be a sequence, so a single value should be 
# placed in a tuple or list.
self.cursor.execute(sql_update, (nVal,))

如果您有多个列/值对,您可以执行以下操作:

cols = ['A', 'B', 'C']
vals = ['a', 'b', 'c']

col_names = ','.join([f'`c`' for c in cols])
values_placeholder = ','.join(['%s'] * len(cols))

sql_update = (f"INSERT INTO `self.tbl` (col_names) VALUES (values_placeholder)")
self.cursor.execute(sql_update, vals)

值不仅是用于插入的数据,也是我们用于比较的数据,例如在WHERE 子句中。因此,可能会像这样创建带有过滤器的更新语句:

sql_update = (f"UPDATE `tbl` SET (`target_col`) = (%s) WHERE (`key_col`) = %s")
self.cursor.execute(sql_update, (nVal, key_id))

但有时SETWHERE 子句的目标可能是一列,例如我们希望根据行中的其他值进行更新。例如,对于key_col 等于other_key_col 的所有行,此语句会将target_col 设置为other_col 的值:

sql_update = (f"UPDATE `tbl` SET (`target_col`) = `other_col` WHERE (`key_col`) = `other_key_col`")
self.cursor.execute(sql_update)

【讨论】:

这很好用!不过应该是self.cursor.execute 你能多解释一下这个方法或者给我一些阅读材料吗?我能够成功地制作插入和删除语句。但是,我不能让 Update 语句像这样工作,我不明白为什么。 sql_update = (f"UPDATE tbl SET (target_col) = (%s) WHERE (key_col) = key_id")。 self.cursor.execute(sql_update, (nVal,))

以上是关于使用 Python 和 mySQL 进行动态 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

mysql-sq;语句

python目录

动态 SQL WHERE 子句生成

python3.5+flask+mysql

连接mysql数据库,创建用户模型

动态sql