【问题标题】:Escaping MySQL reserved words with Python dbapi使用 Python dbapi 转义 MySQL 保留字
【发布时间】:2012-05-16 11:34:10
【问题描述】:

我正在为 MySQL 中的保留字问题寻找一个不错的“pythonic”和“无 SQL 注入”解决方案。

我有以下代码:

alter_sql = 'ALTER TABLE %s ADD COLUMN %s TEXT'      
cursor.execute(alter_sql, sql_params)

当列名是 'index'、'int'、'limit' ....时会出现问题。

在 MySQL shell 中我可以做到:

ALTER TABLE test ADD COLUMN test.limit;

ALTER TABLE test ADD COLUMN `limit`;

但不是

ALTER TABLE test ADD COLUMN 'test.limit';

如何使用 Python 和 MySQLdb 实现这一目标?

【问题讨论】:

    标签: python mysql mysql-python python-db-api


    【解决方案1】:

    也许这会起作用:

    alter_sql = 'ALTER TABLE `%s` ADD COLUMN `%s` TEXT'
    

    UPDATE:这似乎不起作用,因为这种方式绑定参数会添加单引号,因为 MySQLdb 假设这是一个字符串文字。

    或者,您可以在列名之前附加表名吗?

    table_name = MySQLdb.escape_string(table_name)
    escaped_column_name = MySQLdb.escape_string(column_name)
    column_name = '`%s`.`%s`' % (table_name, escaped_column_name)
    
    alter_sql = 'ALTER TABLE %s ADD COLUMN %s TEXT' % (table_name, column_name)
    

    这样,您必须手动转义它们,以避免绑定它们并在其周围添加单引号。

    【讨论】:

    • 那么您使用的查询效果如何?它会输出类似:ALTER TABLE 'mytable' ADD COLUMN ... 这不起作用...
    • 生成的 SQL 将是 ALTER TABLE '`test`' ADD COLUMN '`limit`' TEXT,这是无效的。
    • 您的原始查询。它不是输出类似于我在评论中的内容吗?我试过了,但没有用:“检查语法……”错误
    【解决方案2】:

    来自here

    您可以通过使用 %s 占位符标记并将适当的值绑定到它们来发出相同的语句:

    cursor.execute("""UPDATE animal SET name = %s
                      WHERE name = %s
                   """, ("snake", "turtle"))
    print "Number of rows updated: %d" % cursor.rowcount
    

    关于前面的 execute() 调用的形式,请注意以下几点:

    • 对于要插入语句字符串的每个值,%s 占位符标记应出现一次。
    • 不应在 %s 标记周围加上引号; MySQLdb 会根据需要为您提供报价。
    • 在执行 () 的语句字符串参数之后,提供一个包含要绑定到占位符的值的元组,按照它们在字符串中出现的顺序。如果您只有一个值 x,请将其指定为 (x,) 以指示单元素元组。
    • 将 Python None 值绑定到占位符以将 SQL NULL 值插入到语句中。

    因此,基于此,您应该只预处理您的参数以查看它们是否在保留关键字列表中,如果是,请将表名添加到列名的前缀,例如。

    RESERVED_KEYWORDS = ['LIMIT', 'INT', 'INDEX']
    table_name = 'TESTING'
    column_name = 'LIMIT'
    if column_name in RESERVED_KEYWORDS:
        column_name = '%s.%s' % (table_name, column_name)
    sql_params = [table_name, column_name]
    alter_sql = 'ALTER TABLE %s ADD COLUMN %s TEXT'      
    cursor.execute(alter_sql, sql_params)
    

    【讨论】:

    • 我试过了,但是 MySQLdb 创建了以下 SQL: ALTER TABLE testing ADD COLUMN 'test.limit';由于 test.limit 周围的引号,这是无效的。
    • 如果您 100% 确定您的输入已被清理,您可以执行 sql_query = alter_sql % sql_params; cursor.execute(sql_query) 首先插入 SQL 语句和参数,然后执行它。不完全是最好的方法,但应该有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 2019-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多