web-dev-qa-db-ja.com

SQL INSERTステートメントにPython dictを使用する

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例外を取得します(コンマが自分の持っている値の一部に含まれているという事実に関連すると思います)。上記を行う正しい方法は何ですか?

36
David542

クエリにパラメータープレースホルダーを追加します。これにより、必要なものが得られる場合があります。

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

これをMySQLで使用することについてのコメントは完全ではないと思います。 MySQLdbは列内のパラメーター置換を行わず、値(IIUC)のみを実行します。

placeholders = ', '.join(['%s'] * len(myDict))
columns = ', '.join(myDict.keys())
sql = "INSERT INTO %s ( %s ) VALUES ( %s )" % (table, columns, placeholders)
cursor.execute(sql, myDict.values())

ただし、列でエスケープされていないため、最初に列を確認することをお勧めします。

より完全なソリューションについては、 http://mail.python.org/pipermail/tutor/2010-December/080701.html を参照してください

56
furicle

ここでは常に良い答えですが、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()はリストではなくビューを返します。

また、[〜#〜] not [〜#〜]stmtdict.values()を注ぎます。これは、文字列からjoiningを挿入すると、挿入時にMySQLエラーが発生しました。そのため、常にcur.execute()に動的に配置する必要があります。

15
Blaszard

@furicleの解決策を試しましたが、それでもすべてを文字列として入力します-あなたの辞書が混在している場合、これはあなたが望むように機能しないかもしれません。私は同様の問題を抱えていましたが、これが私が思いついたものです-これはクエリビルダにすぎず、あなたはそれを(変更して)選択して任意のデータベースで動作することができます。ご覧ください!

def ins_query_maker(tablename, rowdict):
keys = Tuple(rowdict)
dictsize = len(rowdict)
sql = ''
for i in range(dictsize) :
    if(type(rowdict[keys[i]]).__== '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

これは粗雑であり、依然として健全性チェックなどが必要ですが、意図したとおりに機能します。口述のために:

tab = {'idnumber': 1, 'fname': 'some', 'lname': 'dude', 'dob': '15/08/1947', 'mobile': 5550000914, 'age' : 70.4}

クエリを実行すると、次の出力が得られます

スイートによって生成されたクエリの結果

2
kilokahn
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)
2
hsamba

私はこのスレッドを使用するために使用し、ずっとシンプルに保つようにしました

_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_を使用してください。

0
Saradhi