programing

SQL INSERT 문에 Python dict 사용

goodsources 2022. 9. 11. 20:12
반응형

SQL INSERT 문에 Python dict 사용

는 를를사 a a a a a a a i를 사용하려고 합니다.dictINSERT으로 다음과

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 예외(쉼표도 일부 값에 포함되어 있는 것과 관련이 있다고 생각합니다)가 표시됩니다.상기의 올바른 방법은 무엇입니까?

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()))

하지만 칼럼에서 탈출할 수는 없으니 먼저 칼럼을 확인하는 것이 좋을 것 같습니다.

보다 완전한 솔루션에 대해서는, http://mail.python.org/pipermail/tutor/2010-December/080701.html 를 참조해 주세요.

조회에 매개 변수 자리 표시자를 추가하려고 합니다.필요한 것을 얻을 수 있습니다.

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

여기에서는 항상 좋은 답변이지만 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에서는 록으로로로 to to in in in in 。 파이썬 3dict.values()목록이 아닌 보기를 반환합니다.

또한, 물을 붓지 마십시오.dict.values()stmt 때문이다.joinMySQL을 사용하다에 항상 래래상 it it it it it에 합니다.cur.execute()역동적으로

파티에 조금 늦었지만, 내 데이터는 보통 이미 받아쓰기 형식이기 때문에 내가 선호하는 다른 방법이 있다.바인드 변수를 %(columnName)s 형식으로 나열하면 실행 시 사전을 사용하여 바인드할 수 있습니다.이렇게 하면 변수가 이름으로 묶여 있기 때문에 열 정렬 문제가 부분적으로 해결됩니다.부분적으로는 삽입의 열과 값 부분이 올바르게 매핑되어 있는지 확인해야 하기 때문입니다.그러나 사전 자체는 임의의 순서로 할 수 있습니다(어차피 dicts는 순서가 정해져 있지 않기 때문에).

이 모든 것을 실현하는 방법은 아마 더 있을 것입니다만, 열 이름을 리스트로 끌어내고, 열과 값의 절을 작성하는 정적 순서를 확보합니다.

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)

이러한 컬럼과 값 절을 동적으로 작성하는 것이 좋은 생각인지 아닌지는 SQL 주입 스레드의 토픽입니다.

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)

@furicle의 솔루션을 시도했지만 모든 것을 문자열로 입력했습니다.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

이것은 조잡하고 건전성 검사 등이 필요하지만 의도한 대로 작동합니다.명령어:

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

쿼리 실행 다음 출력을 얻습니다.

제품군에 의해 생성된 쿼리 결과

이 코드는 나에게 유효했다(Python 3)

fields = (str(list(dictionary.keys()))[1:-1])
values = (str(list(dictionary.values()))[1:-1])
sql = 'INSERT INTO Table (' + fields + ') VALUES (' + values + ')'
cursor.execute(sql)

키와 값을 같은 순서로 출력하는 사전에는 의존합니다.이것이 항상 사실인지 아닌지는 잘 모르겠습니다.

쿼리를 동적으로 구성할 때는 식별자을 모두 올바르게 따옴표로 묶는 것이 중요합니다.그렇지 않으면 위험을 감수해야 합니다.

  • 신뢰할 수 없는 데이터가 처리되는 경우 SQL 주입
  • 열 이름에 따옴표가 필요한 경우 오류 발생(예: 포함된 공간)
  • 따옴표로 묶인 경우 예: " " " )2021-07-11를 붙이지 않고 해도 2003)

견적 값은 DB-API 커넥터에 위임하는 것이 가장 좋습니다.그러나 커넥터 패키지가 항상 식별자를 따옴표로 묶는 방법을 제공하는 것은 아니기 때문에 수동으로 이 작업을 수행해야 할 수도 있습니다.MySQL은 백틱(')을 사용하여 식별자를 따옴표로 묶습니다.

이 코드는 식별자와 값을 따옴표로 묶습니다.MySQLdb, mysql.connector 및 pymysql에서 작동하며 Python 3.5+에서 작동합니다.

data = {'col1': val1, 'col2': val2, ...}

# Compose a string of quoted column names
cols = ','.join([f'`{k}`' for k in data.keys()])

# Compose a string of placeholders for values
vals = ','.join(['%s'] * len(data))

# Create the SQL statement
stmt = f'INSERT INTO `tbl` ({cols}) VALUES ({vals})'

# Execute the statement, delegating the quoting of values to the connector
cur.execute(stmt, tuple(data.values()))

나는 이 실을 내 사용법에 사용했고 훨씬 더 단순하게 유지하려고 노력했다.

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

난 이거면 돼

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()

주의: 커밋하는 것을 잊은 적이 없습니다.그렇지 않으면 표에 삽입된 열과 값을 볼 수 없습니다.

columns = ', '.join(str(x).replace('/', '_')  for x in row_dict.keys())

values = ', '.join("'" + str(x).replace('/', '_') + "'" for x in row_dict.values())

sql = "INSERT INTO %s ( %s ) VALUES ( %s );" % ("tablename", columns, values)

python3에 적용 가능

데이터는 다음과 같습니다.

data = {
        "name" : "fani",
        "surname": "dogru",
        "number" : 271990
    }

다음은 단축 버전입니다.

tablo =  "table_name"
cols = ','.join([f" {k}" for k in data.keys()])
vals = ','.join([f"'{k}'" for k in data.values()])
stmt = f'INSERT INTO {tablo} ({cols}) VALUES ({vals})'

이는 다른 답변에 기초하지만 예약된 단어를 열 이름으로 사용하는 경우 열 이름 주위에 백체크를 사용하여 열 이름에 문자, 숫자 및 밑줄만 포함되도록 하여 SQL 주입 공격을 방지합니다.

저도 비슷한 글을 썼어요.upsert삽입과 동일하게 동작하지만 프라이머리 키를 복제하는 데이터를 덮어씁니다.

import mysql.connector
import re

cnx = mysql.connector.connect(...)

def checkColumnNames(data):
    for name in data.keys():
        assert re.match(r'^[a-zA-Z0-9_]+$',name), "Bad column name: " + name 

def insert(table, data):
    checkColumnNames(data)
    assert table, "No table specified"
    placeholders = ', '.join(['%s'] * len(data))
    columns = '`,`'.join(data.keys())
    sql = "INSERT INTO `%s` (`%s`) VALUES (%s);" % (table, columns, placeholders)
    cnx.cursor().execute(sql, list(data.values()))

def upsert(table, data):
    checkColumnNames(data)
    assert table, "No table specified"
    placeholders = ', '.join(['%s'] * len(data))
    columns = '`,`'.join(data.keys())
    updates = '`' + '`=%s,`'.join(data.keys()) + '`=%s'
    sql = "INSERT INTO `%s` (`%s`) VALUES (%s) ON DUPLICATE KEY UPDATE %s" % (table, columns, placeholders, updates)
    cnx.cursor().execute(sql, list(data.values()) + list(data.values()))

사용 예

insert("animals", {
    "id": 1,
    "name": "Bob",
    "type": "Alligator"
})
cnx.commit()

그럼 어떻게 되는 거죠?

keys = str(dict.keys())
keys.replace('[', '(')
keys.replace(']', ')')
keys.replace("'",'')

vals = str(dict.values())
vals.replace('[', '(')
vals.replace(']', ')')

cur.execute('INSERT INTO table %s VALUES %s' % (keys, vals))

python 3의 경우:

keys = str(dict.keys())[9:].replace('[', '').replace(']', '')
vals = str(dict.values())[11:].replace('[', '').replace(']', '')

...

언급URL : https://stackoverflow.com/questions/9336270/using-a-python-dict-for-a-sql-insert-statement

반응형