85

我很难使用 MySQLdb 模块将信息插入我的数据库。我需要在表中插入 6 个变量。

cursor.execute ("""
    INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation)
    VALUES
        (var1, var2, var3, var4, var5, var6)

""")

有人可以帮我这里的语法吗?

4

7 回答 7

275

请注意对 SQL 查询使用字符串插值,因为它不会正确转义输入参数,并且会使您的应用程序容易受到 SQL 注入漏洞的影响。差异可能看起来微不足道,但实际上它是巨大的

不正确(存在安全问题)

c.execute("SELECT * FROM foo WHERE bar = %s AND baz = %s" % (param1, param2))

正确(转义)

c.execute("SELECT * FROM foo WHERE bar = %s AND baz = %s", (param1, param2))

它增加了混淆,用于在 SQL 语句中绑定参数的修饰符在不同的 DB API 实现之间有所不同,并且 mysql 客户端库使用printf样式语法而不是更普遍接受的“?” 标记(例如使用python-sqlite)。

于 2009-04-22T01:35:26.493 回答
57

你有几个可用的选项。你会想要熟悉 python 的字符串迭代。当您想知道这样的事情时,您将来可能会更成功地搜索这个术语。

更适合查询:

some_dictionary_with_the_data = {
    'name': 'awesome song',
    'artist': 'some band',
    etc...
}
cursor.execute ("""
            INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation)
            VALUES
                (%(name)s, %(artist)s, %(album)s, %(genre)s, %(length)s, %(location)s)

        """, some_dictionary_with_the_data)

考虑到您可能已经在对象或字典中拥有所有数据,第二种格式将更适合您。此外,当您必须在一年内回来更新此方法时,必须在字符串中计算“%s”的出现次数,这很糟糕:)

于 2009-04-22T01:04:31.387 回答
15

链接的文档给出了以下示例:

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

因此,您只需将其调整为您自己的代码 - 例如:

cursor.execute ("""
            INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation)
            VALUES
                (%s, %s, %s, %s, %s, %s)

        """, (var1, var2, var3, var4, var5, var6))

(如果 SongLength 是数字,您可能需要使用 %d 而不是 %s)。

于 2009-04-22T00:53:31.710 回答
7

实际上,即使您的变量 (SongLength) 是数字,您仍然必须使用 %s 对其进行格式化才能正确绑定参数。如果你尝试使用 %d,你会得到一个错误。这是此链接http://mysql-python.sourceforge.net/MySQLdb.html的一小段摘录:

要执行查询,首先需要一个游标,然后可以对其执行查询:

c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
          WHERE price < %s""", (max_price,))

在这个例子中,max_price=5 那么为什么在字符串中使用 %s 呢?因为 MySQLdb 会将其转换为 SQL 文字值,即字符串 '5'。完成后,查询实际上会说“...WHERE price < 5”。

于 2011-03-27T09:31:30.457 回答
7

作为所选答案的替代方案,并且具有与 Marcel 相同的安全语义,这是一种使用 Python 字典指定值的紧凑方法。它的好处是在您添加或删除要插入的列时易于修改:

  meta_cols = ('SongName','SongArtist','SongAlbum','SongGenre')
  insert = 'insert into Songs ({0}) values ({1})'.format(
      ','.join(meta_cols), ','.join( ['%s']*len(meta_cols)))
  args = [ meta[i] for i in meta_cols ]
  cursor = db.cursor()
  cursor.execute(insert,args)
  db.commit()

其中meta是保存要插入的值的字典。更新可以用同样的方式完成:

  meta_cols = ('SongName','SongArtist','SongAlbum','SongGenre')
  update='update Songs set {0} where id=%s'.
        .format(','.join([ '{0}=%s'.format(c) for c in meta_cols ]))
  args = [ meta[i] for i in meta_cols ]
  args.append(songid)
  cursor=db.cursor()
  cursor.execute(update,args)
  db.commit()
于 2013-04-12T20:28:19.750 回答
1

第一个解决方案效果很好。我想在这里添加一个小细节。确保您尝试替换/更新的变量必须是 str 类型。我的 mysql 类型是十进制,但我必须将参数变量设置为 str 才能执行查询。

temp = "100"
myCursor.execute("UPDATE testDB.UPS SET netAmount = %s WHERE auditSysNum = '42452'",(temp,))
myCursor.execute(var)
于 2018-09-12T21:24:13.530 回答
0

这是另一种方法。它记录在 MySQL 官方网站上。 https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html

在精神上,它使用了与@Trey Stout 的回答相同的机制。但是,我发现这个更漂亮,更具可读性。

insert_stmt = (
  "INSERT INTO employees (emp_no, first_name, last_name, hire_date) "
  "VALUES (%s, %s, %s, %s)"
)
data = (2, 'Jane', 'Doe', datetime.date(2012, 3, 23))
cursor.execute(insert_stmt, data)

为了更好地说明对变量的任何需求:

注意:请注意正在完成的转义。

employee_id = 2
first_name = "Jane"
last_name = "Doe"

insert_stmt = (
  "INSERT INTO employees (emp_no, first_name, last_name, hire_date) "
  "VALUES (%s, %s, %s, %s)"
)
data = (employee_id, conn.escape_string(first_name), conn.escape_string(last_name), datetime.date(2012, 3, 23))
cursor.execute(insert_stmt, data)
于 2018-02-01T00:04:21.277 回答