在 python 中 运行 多个 sql 语句的建议方法?
Suggested way to run multiple sql statements in python?
运行 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
?
在MySQLCursor.execute()
的文档中,他们建议使用multi=True
参数:
operation = 'SELECT 1; INSERT INTO t1 VALUES (); SELECT 2'
for result in cursor.execute(operation, multi=True):
...
您可以在模块的源代码中找到 another example。
我在项目中多次遇到这类问题。经过大量研究,我发现了一些要点和建议。
execute()
方法适用于一次一个查询。因为在执行方法期间会处理状态。
I know cursor.execute(operation, params=None, multi=True)
take multiple query. But parameters does not work well in this case and sometimes internal error exception spoil all results too. And code become massive and ambiguous. Even docs also mention this.
executemany(operation, seq_of_params)
不是每次都实施的好习惯。因为产生一个或多个结果集的操作构成未定义的行为,并且允许(但不是必需)实现在检测到已通过调用该操作创建结果集时引发异常。 [来源 - docs]
建议 1-:
Make a list of queries like -:
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-:
Set with dict. [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
You can also use split with script. Not recommended
with connection.cursor() as cursor:
for statement in script.split(';'):
if len(statement) > 0:
cursor.execute(statement + ';')
Note -: I use mostly list of query
approach but in some complex place use make dictionary
approach.
查看 MySQLCursor.execute() 的文档。
它声称您可以传入一个 multi
参数,允许您在一个字符串中 运行 多个查询。
如果 multi 设置为 True,execute() 可以执行操作字符串中指定的多个语句。
multi
是 execute() 调用的可选第二个参数:
operation = 'SELECT 1; INSERT INTO t1 VALUES (); SELECT 2'
for result in cursor.execute(operation, multi=True):
与import mysql.connector
你可以执行以下命令,只需要用你自己的标签替换 t1 和剧集
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)
虽然这会 运行,但您必须确保启用后生效的外键限制不会造成问题。
如果 tablename 是用户可以输入的东西,你应该考虑 table 名字的白名单。
准备好的语句不适用于 table 和列名,因此我们必须使用字符串替换来在正确的位置获得正确的 table 名称,这将使您的代码 漏洞到sql注入
multi=True
是连接器中 运行 4 个命令所必需的,当我测试它时,调试器要求它。
所有答案都是完全有效的,所以我会添加静态类型和 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 安全解决方案。
执行脚本()
这是一次执行多个 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)]
- 执行多次()
通常情况下,必须将大量数据从数据文件插入数据库(对于更简单的情况,采用列表、数组)。多次迭代代码比每次都将每一行都写入数据库要简单。但是在这种情况下不适合使用循环,下面的例子说明了原因。下面解释了 executemany() 的语法和用法,以及如何像循环一样使用它:
来源:GeeksForGeeks: SQL Using Python
查看此来源..这有很多适合您的好东西。
我不会依赖 execute
函数的任何 multi=True
参数,它非常依赖于驱动程序,也不会尝试尝试在 ;
字符上拆分字符串,这可能嵌入到字符串文字中。最直接的方法是创建一个函数 execute_multiple
,它采用要执行的语句列表和一个 rollback_on_error
参数来确定在任何语句导致异常时要执行的操作.
我对 MySQLdb 和 PyMySQL 的体验是,默认情况下它们从 autocommit=0
开始,换句话说,就好像您已经在一个事务中并且需要显式提交。无论如何,该假设适用于下面的代码。如果不是这种情况,那么您应该 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 带参数的准备语句。
情人见仁见智,因此 最佳 做某事的方法是主观的,除非您明确告诉我们如何衡量。我可以看到三个假设选项:
- 使用 MySQLCursor 的
multi
选项(不理想)
- 将查询保留在多行中
- 将查询保留在一行中
您也可以选择更改查询以避免一些不必要的工作。
关于 multi
选项,MySQL documentation 对此非常清楚
If multi is set to True, execute() is able to execute multiple statements specified in the operation string. It returns an iterator that enables processing the result of each statement. However, using parameters does not work well in this case, and it is usually a good idea to execute each statement on its own.
关于选项 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,)
)
Python 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 问题是 What is faster, one big query or many small queries?
最后,使用 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;'
)
我要创建一个存储过程:
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)
保持简单和模块化。当然你应该做一些错误检查,你甚至可以让存储过程return一个代码来指示成功或失败。
运行 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
?
在MySQLCursor.execute()
的文档中,他们建议使用multi=True
参数:
operation = 'SELECT 1; INSERT INTO t1 VALUES (); SELECT 2'
for result in cursor.execute(operation, multi=True):
...
您可以在模块的源代码中找到 another example。
我在项目中多次遇到这类问题。经过大量研究,我发现了一些要点和建议。
execute()
方法适用于一次一个查询。因为在执行方法期间会处理状态。
I know
cursor.execute(operation, params=None, multi=True)
take multiple query. But parameters does not work well in this case and sometimes internal error exception spoil all results too. And code become massive and ambiguous. Even docs also mention this.
executemany(operation, seq_of_params)
不是每次都实施的好习惯。因为产生一个或多个结果集的操作构成未定义的行为,并且允许(但不是必需)实现在检测到已通过调用该操作创建结果集时引发异常。 [来源 - docs]
建议 1-:
Make a list of queries like -:
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-:
Set with dict.
[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
You can also use split with script.
Not recommended
with connection.cursor() as cursor:
for statement in script.split(';'):
if len(statement) > 0:
cursor.execute(statement + ';')
Note -: I use mostly
list of query
approach but in some complex place use makedictionary
approach.
查看 MySQLCursor.execute() 的文档。
它声称您可以传入一个 multi
参数,允许您在一个字符串中 运行 多个查询。
如果 multi 设置为 True,execute() 可以执行操作字符串中指定的多个语句。
multi
是 execute() 调用的可选第二个参数:
operation = 'SELECT 1; INSERT INTO t1 VALUES (); SELECT 2'
for result in cursor.execute(operation, multi=True):
与import mysql.connector
你可以执行以下命令,只需要用你自己的标签替换 t1 和剧集
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)
虽然这会 运行,但您必须确保启用后生效的外键限制不会造成问题。
如果 tablename 是用户可以输入的东西,你应该考虑 table 名字的白名单。
准备好的语句不适用于 table 和列名,因此我们必须使用字符串替换来在正确的位置获得正确的 table 名称,这将使您的代码 漏洞到sql注入
multi=True
是连接器中 运行 4 个命令所必需的,当我测试它时,调试器要求它。
所有答案都是完全有效的,所以我会添加静态类型和 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 安全解决方案。
执行脚本() 这是一次执行多个 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)]
- 执行多次() 通常情况下,必须将大量数据从数据文件插入数据库(对于更简单的情况,采用列表、数组)。多次迭代代码比每次都将每一行都写入数据库要简单。但是在这种情况下不适合使用循环,下面的例子说明了原因。下面解释了 executemany() 的语法和用法,以及如何像循环一样使用它:
来源:GeeksForGeeks: SQL Using Python 查看此来源..这有很多适合您的好东西。
我不会依赖 execute
函数的任何 multi=True
参数,它非常依赖于驱动程序,也不会尝试尝试在 ;
字符上拆分字符串,这可能嵌入到字符串文字中。最直接的方法是创建一个函数 execute_multiple
,它采用要执行的语句列表和一个 rollback_on_error
参数来确定在任何语句导致异常时要执行的操作.
我对 MySQLdb 和 PyMySQL 的体验是,默认情况下它们从 autocommit=0
开始,换句话说,就好像您已经在一个事务中并且需要显式提交。无论如何,该假设适用于下面的代码。如果不是这种情况,那么您应该 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 带参数的准备语句。
情人见仁见智,因此 最佳 做某事的方法是主观的,除非您明确告诉我们如何衡量。我可以看到三个假设选项:
- 使用 MySQLCursor 的
multi
选项(不理想) - 将查询保留在多行中
- 将查询保留在一行中
您也可以选择更改查询以避免一些不必要的工作。
关于 multi
选项,MySQL documentation 对此非常清楚
If multi is set to True, execute() is able to execute multiple statements specified in the operation string. It returns an iterator that enables processing the result of each statement. However, using parameters does not work well in this case, and it is usually a good idea to execute each statement on its own.
关于选项 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,)
)
Python 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 问题是 What is faster, one big query or many small queries?
最后,使用 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;'
)
我要创建一个存储过程:
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)
保持简单和模块化。当然你应该做一些错误检查,你甚至可以让存储过程return一个代码来指示成功或失败。