对SQL INSERT语句使用Python dict

对SQL INSERT语句使用Python dict,python,mysql,sql,Python,Mysql,Sql,我正在尝试使用dict执行SQLINSERT。逻辑基本上是: INSERT INTO table (dict.keys()) VALUES dict.values() 然而,我很难找到正确的语法/流程来完成这项工作。这就是我目前拥有的: # data = {...} sorted_column_headers_list = [] sorted_column_values_list = [] for k, v in data.items(): sorted_column_headers_

我正在尝试使用
dict
执行SQL
INSERT
。逻辑基本上是:

INSERT INTO table (dict.keys()) VALUES dict.values()
然而,我很难找到正确的语法/流程来完成这项工作。这就是我目前拥有的:

# data = {...}
sorted_column_headers_list = []
sorted_column_values_list = []
for k, v in data.items():
    sorted_column_headers_list.append(k)
    sorted_column_values_list.append(v)
sorted_column_headers_string = ', '.join(sorted_column_headers_list)
sorted_column_values_string = ', '.join(sorted_column_values_list)

cursor.execute("""INSERT INTO title (%s) 
            VALUES (%s)""", 
            (sorted_column_headers_string, sorted_column_values_string))

由此我得到了一个SQL异常(我认为这与逗号也包含在我的一些值中这一事实有关)。执行上述操作的正确方法是什么?

您想在查询中添加参数占位符。这可能会满足您的需要:

qmarks = ', '.join('?' * len(myDict))
qry = "Insert Into Table (%s) Values (%s)" % (qmarks, qmarks)
cursor.execute(qry, myDict.keys() + myDict.values())

我认为对MySQL使用这个的评论还不够完整。MySQLdb不在列中进行参数替换,只在值(IIUC)中进行替换-因此可能更像

placeholders = ', '.join(['%s'] * len(myDict))
columns = ', '.join(myDict.keys())
sql = "INSERT INTO %s ( %s ) VALUES ( %s )" % (table, columns, placeholders)
# valid in Python 2
cursor.execute(sql, myDict.values())
# valid in Python 3
cursor.execute(sql, list(myDict.values()))
但是,您无法在列上转义,因此您可能需要先检查它们

有关更完整的解决方案,请参见
table='mytable'    
columns_string= '('+','.join(myDict.keys())+')'    
values_string = '('+','.join(map(str,myDict.values()))+')'    
sql = """INSERT INTO %s %s
     VALUES %s"""%(table, columns_string,values_string)
对于python 3:
这里的答案总是很好,但是在Python 3中,您应该编写以下内容:

placeholder = ", ".join(["%s"] * len(dict))
stmt = "insert into `{table}` ({columns}) values ({values});".format(table=table_name, columns=",".join(dict.keys()), values=placeholder)
cur.execute(stmt, list(dict.values()))
不要忘记将
dict.values()
转换为列表,因为在Python 3中,
dict.values()
返回的是视图,而不是列表


另外,不要在
stmt
中倒
dict.values()
,因为它通过
join
ing从字符串中删除引号,从而导致MySQL在插入时出错。因此,您应该始终动态地将其放入
cur.execute()

我尝试了@furicle的解决方案,但它仍然以字符串的形式输入所有内容-如果您的dict是一个混合的dict,那么这可能无法像您希望的那样工作。我有一个类似的问题,这就是我提出的-这只是一个查询生成器,您可以使用它(进行更改)来处理您选择的任何数据库。看一看

def ins_query_maker(tablename, rowdict):
    keys = tuple(rowdict)
    dictsize = len(rowdict)
    sql = ''
    for i in range(dictsize) :
        if(type(rowdict[keys[i]]).__name__ == 'str'):
            sql += '\'' + str(rowdict[keys[i]]) + '\''
        else:
            sql += str(rowdict[keys[i]])
        if(i< dictsize-1):
            sql += ', '
    query = "insert into " + str(tablename) + " " + str(keys) + " values (" + sql + ")"
    print(query) # for demo purposes we do this
    return(query) #in real code we do this
运行查询时,我得到以下输出


我使用这个线程,并试图让它更简单

ins_qry = "INSERT INTO {tablename} ({columns}) VALUES {values};" .format(
            tablename=my_tablename,
            columns=', '.join(myDict.keys()),
            values=tuple(myDict.values())
        )
cursor.execute(ins_qry)
如果您需要插入行的主键,请确保使用
db_connection.commit()
cursor.lastrowid
,提交插入的数据。join(str(x)。替换行中x的('/','.')dict.keys())

values=',join(“”+str(x).replace(“/”,“'.'+”)行中x的“/”,“'.'+”)

sql=“插入到%s(%s)值(%s);”%(“表名”、列、值)

适用于python3

此代码对我(python3)有效:


它确实依赖于字典以相同的顺序输出其键和值。我不清楚这是否总是正确的:)

我参加聚会有点晚了,但我倾向于选择另一种方式,因为我的数据通常已经以dict的形式存在。如果以%(columnName)的形式列出绑定变量,则可以使用字典在执行时绑定它们。这部分解决了列排序问题,因为变量是按名称绑定的。我之所以这样说,部分是因为您仍然必须确保insert的列和值部分映射正确;但是字典本身可以是任意顺序的(因为不管怎样,dicts都是无序的)

可能有一种更具python风格的方法来实现这一切,但将列名拉入列表并对其进行处理可以确保构建columns&values子句的顺序是静态的

data_dict = {'col1': 'value 1', 'col2': 'value 2', 'col3': 'value 3'}
columns = data_dict.keys()
cols_comma_separated = ', '.join(columns)
binds_comma_separated = ', '.join(['%(' + item + ')s' for item in columns])

sql = f'INSERT INTO yourtable ({cols_comma_separated}) VALUES ({binds_comma_separated})'

cur.execute(sql, data_dict)
现在,像这样动态构建columns&values子句是否是一个好主意是SQL注入线程的一个主题。

这对我来说很有用

cursor.execute("INSERT INTO table (col) VALUES ( %(col_value) )", 
        {'col_value': 123})

如果你有一个列表,其中有很多字典 例如:lst=[d1,d2,d3,d4]

下面的一个将为我工作:

for i in lst:
    placeholders = ', '.join(['%s'] * len(i))
    columns = ', '.join(i.keys())
    sql = "INSERT INTO %s ( %s ) VALUES ( %s )" % (table, columns, placeholders)
    cursor.execute(sql,list(i.values()))
conn.commit()

注意:永远不要忘记提交,否则您将无法看到插入表中的列和值

光标。execute(qry,columns,myDict.values())
有语法错误
cursor.execute(qry,myDict.values())
是正确的格式。dict是否有任何排序问题?这是有史以来最好的答案@zs1986 Per,dict中不应该存在排序问题:如果调用
items()
keys()
values()
iteritems()
iterkeys()
itervalues()
,则列表将直接对应。使用
列=“
`
%s
``````
'.join(myDict.keys())
如果您的列名包含连字符或其他特殊/保留字符yi:这对我不起作用,但@furicle answer使用
myDict.keys()
这种方式无法保证键之间的任何特定顺序。
myDict.values()
甚至可能不会按照
myDict.keys()
@PatrikIselind返回的相应顺序生成值-不正确。请参阅。只要没有中间的更改(上述更改是不可能的)它们将始终以相同的顺序返回。此字段会收到错误,因为它会将其检测为字符串,尽管SQL希望将其作为可变答案。为了更实用,您需要在联接中替换单个引号。“+”,“.join(myDict.keys())+“\”)或更好的“(“+”,“.join(myDict.keys())+”)“这似乎是个好答案——谢谢你。但是使用
dict
作为变量名可能并不理想。。。我还从
pymysql
中得到一个
AttributeError:“dict\u values”对象没有属性“translate”
错误。需要做更多的测试。我必须这样做,以摆脱AttributeError。这是一个很大的帮助,您将如何包括“重复密钥更新”?德克萨斯州!危险!这不会逃逸值或使用?-substitution,因此容易受到SQL注入攻击。您可以通过使用SQL参数替换来摆脱手动逃逸的需要,SQL参数替换是MySQL的python包装中的
%s
。我想可以这样做。这是我提出的一个旧实现,但后来我转向了NoSQL数据库
fields = (str(list(dictionary.keys()))[1:-1])
values = (str(list(dictionary.values()))[1:-1])
sql = 'INSERT INTO Table (' + fields + ') VALUES (' + values + ')'
cursor.execute(sql)
data_dict = {'col1': 'value 1', 'col2': 'value 2', 'col3': 'value 3'}
columns = data_dict.keys()
cols_comma_separated = ', '.join(columns)
binds_comma_separated = ', '.join(['%(' + item + ')s' for item in columns])

sql = f'INSERT INTO yourtable ({cols_comma_separated}) VALUES ({binds_comma_separated})'

cur.execute(sql, data_dict)
cursor.execute("INSERT INTO table (col) VALUES ( %(col_value) )", 
        {'col_value': 123})
for i in lst:
    placeholders = ', '.join(['%s'] * len(i))
    columns = ', '.join(i.keys())
    sql = "INSERT INTO %s ( %s ) VALUES ( %s )" % (table, columns, placeholders)
    cursor.execute(sql,list(i.values()))
conn.commit()