python에서 여러 sql 문을 실행할 수 있는 방법을 제안하시겠습니까?
python에서 다음과 같은 것을 실행하는 제안된 방법은 무엇입니까?
self.cursor.execute('SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS %s; SET FOREIGN_KEY_CHECKS=1' % (table_name,))
를 들어,이 세 , .self.cursor.execute(...)
진술? 이외에 사용해야 할 특정한 방법이 있습니까 이외에 해야 할 ?cursor.execute(...)
이와 같은 일을 하는 것, 또는 이것을 하는 데 제안된 실천 방법은 무엇입니까?현재 제가 가지고 있는 코드는 다음과 같습니다.
self.cursor.execute('SET FOREIGN_KEY_CHECKS=0;')
self.cursor.execute('DROP TABLE IF EXISTS %s;' % (table_name,))
self.cursor.execute('SET FOREIGN_KEY_CHECKS=1;')
self.cursor.execute('CREATE TABLE %s select * from mytable;' % (table_name,))
보시다시피, 모든 것이 따로따로 운영됩니다. 이 좋은 인지 아닌지 잘 (위의 하는 가장 좋은 그래서 저는 이것이 좋은 생각인지 아닌지 확신할 수 없습니다.(아니면 위의 작업을 수행하는 가장 좋은 방법은 무엇인지)..BEGIN...END
?
저장 프로시저를 만듭니다.
DROP PROCEDURE IF EXISTS CopyTable;
DELIMITER $$
CREATE PROCEDURE CopyTable(IN _mytable VARCHAR(64), _table_name VARCHAR(64))
BEGIN
SET FOREIGN_KEY_CHECKS=0;
SET @stmt = CONCAT('DROP TABLE IF EXISTS ',_table_name);
PREPARE stmt1 FROM @stmt;
EXECUTE stmt1;
SET FOREIGN_KEY_CHECKS=1;
SET @stmt = CONCAT('CREATE TABLE ',_table_name,' as select * from ', _mytable);
PREPARE stmt1 FROM @stmt;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END$$
DELIMITER ;
그리고 나서 그냥 달려라:
args = ['mytable', 'table_name']
cursor.callproc('CopyTable', args)
단순하고 모듈식으로 유지할 수 있습니다.물론 당신은 일종의 오류 검사를 해야 하며 심지어 저장된 프로시저가 성공 또는 실패를 나타내는 코드를 반환하도록 할 수도 있습니다.
의 문서에서, 그들은 다음을 사용할 것을 제안합니다.multi=True
매개 변수:
operation = 'SELECT 1; INSERT INTO t1 VALUES (); SELECT 2'
for result in cursor.execute(operation, multi=True):
...
모듈의 소스 코드에서 다른 예를 찾을 수 있습니다.
나는 그 어떤 것에도 의지하지 않을 것입니다.multi=True
execute
- 합니다.;
문자열 리터럴에 포함될 수 있는 문자입니다.가장 입니다라는입니다.execute_multiple
a, 를 합니다.rollback_on_error
하나의 문에서 예외가 발생할 경우 수행할 작업을 결정하는 매개 변수입니다.
및 PyMySQLDB PyMySQLDB 에은 으로 SQL 합니다에서.autocommit=0
, 마치 처럼, , 어쨌든, 그 가정은 아래의 코드를 유지합니다. 않다면,1. 1.은을 설정하고, 1.다를 .autocommit=0
연결 후에 또는 2. 이 하여 이 코드를 수정하여 다음과 같이 트랜잭션을 시작합니다에 따라 합니다.try
def execute_multiple(conn, statements, rollback_on_error=True):
"""
Execute multiple SQL statements and returns the cursor from the last executed statement.
:param conn: The connection to the database
:type conn: Database connection
:param statements: The statements to be executed
:type statements: A list of strings
:param: rollback_on_error: Flag to indicate action to be taken on an exception
:type rollback_on_error: bool
:returns cursor from the last statement executed
:rtype cursor
"""
try:
cursor = conn.cursor()
for statement in statements:
cursor.execute(statement)
if not rollback_on_error:
conn.commit() # commit on each statement
except Exception as e:
if rollback_on_error:
conn.rollback()
raise
else:
if rollback_on_error:
conn.commit() # then commit only after all statements have completed successfully
또한 매개변수 목록과 함께 준비된 문을 처리하는 버전을 가질 수도 있습니다.
def execute_multiple_prepared(conn, statements_and_values, rollback_on_error=True):
"""
Execute multiple SQL statements and returns the cursor from the last executed statement.
:param conn: The connection to the database
:type conn: Database connection
:param statements_and_values: The statements and values to be executed
:type statements_and_values: A list of lists. Each sublist consists of a string, the SQL prepared statement with %s placeholders, and a list or tuple of its parameters
:param: rollback_on_error: Flag to indicate action to be taken on an exception
:type rollback_on_error: bool
:returns cursor from the last statement executed
:rtype cursor
"""
try:
cursor = conn.cursor()
for s_v in statements_and_values:
cursor.execute(s_v[0], s_v[1])
if not rollback_on_error:
conn.commit() # commit on each statement
except Exception as e:
if rollback_on_error:
conn.rollback()
raise
else:
if rollback_on_error:
conn.commit() # then commit only after all statements have completed successfully
return cursor # return the cursor in case there are results to be processed
예를 들어,
cursor = execute_multiple_prepared(conn, [('select * from test_table where count = %s', (2000,))], False)
인정하건대, 위 호출에는 매개 변수가 포함된 SQL이 하나만 준비되어 있었습니다.
아름다움은 보는 사람의 눈에 있기 때문에 어떤 것을 하는 가장 좋은 방법은 어떻게 측정해야 하는지 우리에게 명시적으로 말하지 않는 한 주관적입니다.제가 볼 수 있는 가상 옵션은 세 가지입니다.
- 을 합니다.
multi
MySQLCursor 옵션(이상적이지 않음) - 쿼리를 여러 행으로 유지
- 쿼리를 한 행에 보관
또는 불필요한 작업을 방지하기 위해 쿼리를 변경할 수도 있습니다.
multi
옵션 MySQL 문서는 꽤 명확합니다.
multi를 True로 설정하면 execute()는 연산 문자열에 지정된 여러 문을 실행할 수 있습니다.각 문의 결과를 처리할 수 있는 반복기를 반환합니다.그러나 이 경우 모수를 사용하는 것은 잘 작동하지 않으며, 각 문을 자체적으로 실행하는 것이 좋습니다.
옵션 2. 및 3. 코드를 보는 방법에 대한 순수한 선호 사항입니다.다가(가) .autocommit=FALSE
됩니다를 합니다.cursor.execute(...)
단일 트랜잭션에 호출합니다. 두 즉,다입니다
self.cursor.execute('SET FOREIGN_KEY_CHECKS=0;')
self.cursor.execute('DROP TABLE IF EXISTS %s;' % (table_name,))
self.cursor.execute('SET FOREIGN_KEY_CHECKS=1;')
self.cursor.execute('CREATE TABLE %s select * from mytable;' % (table_name,))
대
self.cursor.execute(
'SET FOREIGN_KEY_CHECKS=0;'
'DROP TABLE IF EXISTS %s;' % (table_name,)
'SET FOREIGN_KEY_CHECKS=1;'
'CREATE TABLE %s select * from mytable;' % (table_name,)
)
파이썬 3.6은 굉장히 우아한 f-스트링을 선보였는데, 사용할 수 있다면 사용해야 합니다.:)
self.cursor.execute(
'SET FOREIGN_KEY_CHECKS=0;'
f'DROP TABLE IF EXISTS {table_name};'
'SET FOREIGN_KEY_CHECKS=1;'
f'CREATE TABLE {table_name} select * from mytable;'
)
행을 조작하기 시작할 때는 이 기능이 더 이상 유지되지 않습니다. 이 경우에는 쿼리에 따라 달라지므로 관련된 경우 프로파일을 작성해야 합니다.관련 SO 질문으로는 하나의 큰 쿼리와 많은 작은 쿼리 중 무엇이 더 빠릅니까?
으로, 를 이 더 수 있습니다.TRUNCATE
DROP TABLE
특별한 이유가 없다면요
self.cursor.execute(
f'CREATE TABLE IF NOT EXISTS {table_name};'
'SET FOREIGN_KEY_CHECKS=0;'
f'TRUNCATE TABLE {table_name};'
'SET FOREIGN_KEY_CHECKS=1;'
f'INSERT INTO {table_name} SELECT * FROM mytable;'
)
저는 프로젝트에서 이런 유형의 문제에 여러 번 부딪혔습니다.많은 연구 끝에 몇 가지 점과 제안을 찾았습니다.
execute()
메서드는 한 번에 하나의 쿼리에 대해 잘 작동합니다.왜냐하면 실행 방법은 상태를 관리하기 때문입니다.
알고있어요
cursor.execute(operation, params=None, multi=True)
여러 가지 질문을 받다그러나 이 경우 매개 변수가 제대로 작동하지 않으며 내부 오류 예외로 인해 모든 결과가 손상되는 경우도 있습니다.그리고 코드는 방대하고 모호해집니다.심지어 의사들도 이것을 언급합니다.
executemany(operation, seq_of_params)
매번 실행하는 것은 좋은 방법이 아닙니다.하나 이상의 결과 집합을 생성하는 연산은 정의되지 않은 동작을 구성하며, 구현은 연산의 호출로 결과 집합이 생성되었음을 감지할 때 예외를 발생시키는 것이 허용(필요하지는 않음)되기 때문입니다.[소스 - 문서]
제안 1-:
다음과 같은 쿼리 목록을 만듭니다.
table_name = 'test'
quries = [
'SET FOREIGN_KEY_CHECKS=0;',
'DROP TABLE IF EXISTS {};'.format(table_name),
'SET FOREIGN_KEY_CHECKS=1;',
'CREATE TABLE {} select * from mytable;'.format(table_name),
]
for query in quries:
result = self.cursor.execute(query)
# Do operation with result
제안 2-:
구술로 설정합니다.
[you can also make this by executemany for recursive parameters for some special cases.]
quries = [
{'DROP TABLE IF EXISTS %(table_name);':{'table_name': 'student'}},
{'CREATE TABLE %(table_name) select * from mytable;':
{'table_name':'teacher'}},
{'SET FOREIGN_KEY_CHECKS=0;': ''}
]
for data in quries:
for query, parameter in data.iteritems():
if parameter == '':
result = self.cursor.execute(query)
# Do something with result
else:
result = self.cursor.execute(query, parameter)
# Do something with result
스크립트와 함께 split을 사용할 수도 있습니다.
Not recommended
with connection.cursor() as cursor:
for statement in script.split(';'):
if len(statement) > 0:
cursor.execute(statement + ';')
-: -: 합니다를 합니다.
list of query
하지만 어떤 하기를 .dictionary
접근.
MySQL Cursor에 대한 설명서를 봅니다.실행에 옮기다
당신이 그 안에서 통과할 수 있다고 주장합니다.multi
하나의 문자열에서 여러 개의 쿼리를 실행할 수 있는 매개 변수입니다.
multi를 True로 설정하면 execute()는 연산 문자열에 지정된 여러 문을 실행할 수 있습니다.
multi
두(선택 행()입니다입니다.
operation = 'SELECT 1; INSERT INTO t1 VALUES (); SELECT 2'
for result in cursor.execute(operation, multi=True):
와 함께import mysql.connector
당신은 명령을 따를 수 있습니다. 단지 t1과 에피소드를 당신만의 tabaes로 바꾸기만 하면 됩니다.
tablename= "t1"
mycursor.execute("SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS {}; SET FOREIGN_KEY_CHECKS=1;CREATE TABLE {} select * from episodes;".format(tablename, tablename),multi=True)
이 작업이 실행되는 동안 활성화한 후 적용될 외래 키 구속 장치가 문제를 일으키지 않도록 해야 합니다.
테이블 이름이 사용자가 입력할 수 있는 항목인 경우 테이블 이름의 화이트리스트를 고려해야 합니다.
준비된 문은 테이블 및 열 이름과 함께 작동하지 않으므로 올바른 위치에서 올바른 테이블 이름을 얻기 위해 문자열 교체를 사용해야 합니다. 이는 코드를 sql 주입에 취약하게 만듭니다.
multi=True
커넥터에서 4개의 명령어를 실행하기 위해 필요한데, 테스트해보니 디버거에서 요구했습니다.
executivecript() 여러 SQL 문을 한 번에 실행할 수 있는 편리한 방법입니다.파라미터로 받는 SQL 스크립트를 실행합니다.구문:
sqlite3.connect.executescript(script)
예제 코드:
import sqlite3
# Connection with the DataBase
# 'library.db'
connection = sqlite3.connect("library.db")
cursor = connection.cursor()
# SQL piece of code Executed
# SQL piece of code Executed
cursor.executescript("""
CREATE TABLE people(
firstname,
lastname,
age
);
CREATE TABLE book(
title,
author,
published
);
INSERT INTO
book(title, author, published)
VALUES (
'Dan Clarke''s GFG Detective Agency',
'Sean Simpsons',
1987
);
""")
sql = """
SELECT COUNT(*) FROM book;"""
cursor.execute(sql)
# The output in fetched and returned
# as a List by fetchall()
result = cursor.fetchall()
print(result)
sql = """
SELECT * FROM book;"""
cursor.execute(sql)
result = cursor.fetchall()
print(result)
# Changes saved into database
connection.commit()
# Connection closed(broken)
# with DataBase
connection.close()
출력:
[(1,)] [('댄 클라크의 GFG 탐정단', 'Sean Simpsons', 1987)]
- executive many() 데이터 파일에서 데이터베이스에 대량의 데이터를 삽입해야 하는 경우가 많습니다(간단히 사례를 들어 목록, 배열).매번 한 줄씩 데이터베이스에 기록하는 것보다 코드를 여러 번 반복하는 것이 간단합니다.그러나 이 경우 루프를 사용하는 것은 적합하지 않을 것이며, 아래의 예는 그 이유를 보여줍니다.executemany()의 구문 및 사용법은 아래와 같이 설명되며 루프처럼 사용될 수 있는 방법은 다음과 같습니다.
출처: GeeksForGeeks: SQL Using Python 이 출처 확인..이것은 당신에게 좋은 것들을 많이 가지고 있습니다.
과 로 closing
상황 관리자.
from contextlib import closing
from typing import List
import mysql.connector
import logging
logger = logging.getLogger(__name__)
def execute(stmts: List[str]) -> None:
logger.info("Starting daily execution")
with closing(mysql.connector.connect()) as connection:
try:
with closing(connection.cursor()) as cursor:
cursor.execute(' ; '.join(stmts), multi=True)
except Exception:
logger.exception("Rollbacking changes")
connection.rollback()
raise
else:
logger.info("Finished successfully")
연결이나 커서가 잘못 연결된 것이 아니라면 현재 보유 중인 mysql 드라이버 버전에 따라 컨텍스트 관리자가 아닐 수 있으므로 이는 pythonic 안전 솔루션입니다.
언급URL : https://stackoverflow.com/questions/62584640/suggested-way-to-run-multiple-sql-statements-in-python
'programing' 카테고리의 다른 글
"for=id"를 사용하지 않고 확인란에 레이블을 연결할 수 있습니까? (0) | 2023.10.07 |
---|---|
ipv4 범위 필터링 시 SQL 성능 (0) | 2023.10.07 |
외부 키(MySQL) 추가 방법 (0) | 2023.10.07 |
memcpy의 내부 구현은 어떻게 이루어집니까? (0) | 2023.10.07 |
@Html은 어떻습니까?Microsoft ASP에서 BeginForm() work?와 검색 결과를 입력합니다.순 MVC 5 튜토리얼? (0) | 2023.10.07 |