【问题标题】:Generate an SQL statement to insert multiple lines into a MySQL database at once using Python使用 Python 生成 SQL 语句以一次将多行插入 MySQL 数据库
【发布时间】:2013-01-20 15:27:08
【问题描述】:

我正在尝试生成一个变量,我可以使用该变量将多行插入 MySQL 数据库或保存到文件中。

由于我是 python 新手,我的脑海里现在嗡嗡作响着我必须学习的所有新概念,我正在寻找一点保证,我的方法是一个好的方法。

将多个项目插入表的 SQL 语法如下:

INSERT INTO 'tablename' ('column1', 'column2') VALUES
  ('data1', 'data2'),
  ('data3', 'data4'),
  ('data5', 'data6'),
  ('data7', 'data8');

这是我的代码:

import shelve

shelf = shelve.open('test.db', flag='r')

sql = "INSERT INTO 'myTableName' ( "
sql += ", ".join(shelf.itervalues().next())
sql = " ) VALUES "
for s in shelf: 

  sql += "( "
  sql += ', '.join(['\'%s\'' % ( value ) for (key, value) in shelf[s].items()])
  sql += " ),"

shelf.close()

print sql

它几乎可以工作(它有一个尾随,而不是一个 ; 在最后的 sql 添加)但我确信必须有一个更简洁的方法。你能告诉我它是什么吗?

【问题讨论】:

  • 一个提示,不要用单引号将 tableName 括起来,因为它是标识符而不是字符串文字。
  • JW,你的意思是我应该用“INSERT INTO myTableName (”代替吗?
  • 是的,或者如果您想安全使用反引号,“INSERT INTO `tablename` (`column1`, `column2`) VALUES....”以及 columnNames
  • 谢谢你,JW,我不知道这一点,因为我只是一个初学者。我会将其添加到我不断增长的要阅读的内容列表中。
  • 在需要时使用反引号,例如当您使用保留关键字时,并且您的表或列名称上有空格或类似“hello-world”的内容

标签: python mysql sql database insert


【解决方案1】:

不要从字符串连接生成 SQL。改用 SQL 参数:

cursor = connection.cursor()

cursor.executemany('INSERT INTO 'tablename' ('column1', 'column2') VALUES (%s, %s)',
        [sub.values() for sub in shelf.values()])

然后数据库可以重用INSERT 语句(它为它准备一个查询计划),数据库客户端将为您处理引用,并且您可以防止 SQL 注入攻击启动。

【讨论】:

  • 如何使用这种方法将正在使用的语句保存到文件中?我并不总是想执行语句。
  • @user1464409:那么就保存语句,稍后再执行;如果可以的话,你真的想避免插入值。
  • 我读到 MySQLdb 在发送查询之前使用字符串插值来构建查询,因此服务器无法重用 insert 语句。同样使用executemany 应该更快。
  • @Dikei:如果 MySQLdb 这样做,那将是一个遗憾,但至少它会在这种情况下正确处理引用。更新为使用executemany()
  • @user1464409:我刚刚编辑了答案以改用executemany()。 :-)
【解决方案2】:

由于该问题专门询问如何生成 SQL 插入语句,而不是如何插入 SQL 数据库,因此我提供以下代码:

def sterilize(s):
    if type(s) is str:
        return s.replace("'", "`").replace("\n", " ")
    else:
        return s

class insert_writer:
    def __init__(self, table_name, file_name, batch_size=42069):
        self.table_name = table_name
        self.file_name = file_name
        self.count = 0
        self.rows = 0
        self.batch_size = batch_size
        self.schema = []

    def __enter__(self):
        self.out_stream = open(self.file_name, "w")
        return self

    def __exit__(self, *args):
        self.out_stream.write(";\n")
        self.out_stream.close()

    def add_row(self, row_data):
        items = list(row_data.items())
        items.sort()
        keys = [x[0] for x in items]
        values = ["'%s'" % sterilize(x[1]) for x in items]
        output = ""
        if self.rows is 0:
            self.schema = keys

        if keys != self.schema:
            print(f"row {self.rows}: {keys} mismatches {self.schema}\n")

        if self.count is 0:
            output += ";\nINSERT INTO "
            output += self.table_name
            output += "(" + ", ".join(keys) + ") VALUES "
            output += "\n(" + ", ".join(values) + ")"
        else:
            output += ",\n(" + ", ".join(values) + ")"

        self.count = self.count + 1 if self.count < self.batch_size - 1 else 0
        self.rows += 1
        self.out_stream.write(output)

【讨论】:

    猜你喜欢
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多