可以用pymysql插入字典吗?

Dim*_*ims 3 python mysql dictionary pymysql

我有一本与数据库中名称和列相同的字典。我可以按原样插入它,而不用INSERT INTO再次手动键入所有列名称来重写语句吗?

更新

问题在于pymysql能力。您不需要编写代码,SQL从字典中构建语句。

Mar*_*ers 6

PyMySQL 就像任何其他DB-API 2.0 适配器一样;参数必须作为位置或命名占位符放置在 SQL 查询中。如果您想避免预先显式命名列,则必须以编程方式生成占位符。

当您使用参数语法时,PyMySQL 支持使用%(name)s参数字典执行查询。要从字典生成插入语句,您可以使用:

def escape_name(s):
    """Escape name to avoid SQL injection and keyword clashes.

    Doubles embedded backticks, surrounds the whole in backticks.

    Note: not security hardened, caveat emptor.

    """
    return '`{}`'.format(s.replace('`', '``'))

names = list(dict_of_params)
cols = ', '.join(map(escape_name, names))  # assumes the keys are *valid column names*.
placeholders = ', '.join(['%({})s'.format(name) for name in names])

query = 'INSERT INTO TABLENAME ({}) VALUES ({})'.format(cols, placeholders)
cursor.execute(query, dict_of_params)
Run Code Online (Sandbox Code Playgroud)


小智 6

我意识到这是一个相当老的问题,但这是谷歌给我的“pymysql插入字典”的最佳结果,所以在花了一些时间试图找出最好的方法后,我想我会分享。这是我在这里发表的第一篇文章(尽管有 42 年的 DP/IT 经验!!)所以请对我温柔点:)

请注意,这个答案特定于 pymysql - 据我了解,其他 mySQL/MariaDB 连接器可能会以不同的方式处理绑定变量的替换(尽管应该可以调整 VALUES 上的连接参数以生成所需的任何格式)。

假设 OP 描述的字典保存在一个名为 data 的变量中,如下所示:

data = {'season' : 60, 'game' : 10, 'player' : 'JS1', 'runs' : 18}
Run Code Online (Sandbox Code Playgroud)

并且我们在变量编写器中有一个现有的 pymysql 写入启用连接,那么这种通用方法应该达到预期的结果:

   writer.begin()
   try:
      with writer.cursor() as insert_cursor:
         sqlcmd = (
          f"INSERT INTO Scores ({', '.join(data.keys())}) "
          f"VALUES (%({')s, %('.join(data.keys())})s)")
         insert_cursor.execute(sqlcmd, data)
         inserted = insert_cursor.rowcount
   except:
      writer.rollback()
      print('\aScores table insert failed. Transaction rolled back')
      raise
   writer.commit()
   print('Inserted', inserted, 'row(s) into Scores table')
Run Code Online (Sandbox Code Playgroud)

如果我们将数据扩展为字典列表,那就更好了:

data = [
 {'season' : 60, 'game' : 10, 'player' : 'JS1', 'runs' : 18},
 {'season' : 60, 'game' : 12, 'player' : 'JS1', 'runs' : 0},
 {'season' : 60, 'game' : 13, 'player' : 'JS1', 'runs' : 60},
...
 ]
Run Code Online (Sandbox Code Playgroud)

然后,通过一些小的调整,我们可以使用executemany 将它们全部插入一次调用中:

   writer.begin()
   try:
      with writer.cursor() as insert_cursor:
         sqlcmd = (
          f"INSERT INTO Scores ({', '.join(data[0].keys())}) "
          f"VALUES (%({')s, %('.join(data[0].keys())})s)")
         insert_cursor.executemany(sqlcmd, data)
         inserted = insert_cursor.rowcount
   except:
      writer.rollback()
      print('\aScores table insert failed. Transaction rolled back')
      raise
   writer.commit()
   print('Inserted', inserted, 'row(s) into Scores table')
Run Code Online (Sandbox Code Playgroud)