我有同样的问题,但这里的答案都没有解决它。我无法让“SET NOCOUNT ON”工作,也无法使用表变量进行单个批处理操作。起作用的是分两批使用临时表,但整天都在寻找正确的语法。下面的代码在第一批中创建并填充一个临时表,然后在第二批中,它使用数据库名称执行存储过程,并在存储过程名称前加上两个点。此语法对于避免错误“找不到存储过程'x'。(2812) (SQLExecDirectW))”很重要。
def create_incidents(db_config, create_table, columns, tuples_list, upg_date):
"""Executes trackerdb-dev mssql stored proc.
Args:
config (dict): config .ini file with mssqldb conn.
create_table (string): temporary table definition to be inserted into 'CREATE TABLE #TempTable ()'
columns (tuple): columns of the table table into which values will be inserted.
tuples_list (list): list of tuples where each describes a row of data to insert into the table.
upg_date (string): date on which the items in the list will be upgraded.
Returns:
None
"""
sql_create = """IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
DROP TABLE #TempTable;
CREATE TABLE #TempTable ({});
INSERT INTO #TempTable ({}) VALUES {};
"""
columns = '"{}"'.format('", "'.join(item for item in columns))
# this "params" variable is an egregious offense against security professionals everywhere. Replace it with parameterized queries asap.
params = ', '.join([str(tupl) for tupl in tuples_list])
sql_create = sql_create.format(
create_table
, columns
, params)
msconn.autocommit = True
cur = msconn.cursor()
try:
cur.execute(sql_create)
cur.execute("DatabaseName..TempTable_StoredProcedure ?", upg_date)
except pyodbc.DatabaseError as err:
print(err)
else:
cur.close()
return
create_table = """
int_column int
, name varchar(255)
, datacenter varchar(25)
"""
create_incidents(
db_config = db_config
, create_table = create_table
, columns = ('int_column', 'name', 'datacenter')
, cloud_list = tuples_list
, upg_date = '2017-09-08')
存储过程使用IF OBJECT_ID('tempdb..#TempTable') IS NULL
语法来验证临时表是否已创建。如果有,则程序从中选择数据并继续。如果尚未创建临时表,则 proc 中止。这会强制存储过程使用在存储过程本身之外但在同一会话中创建的#TempTable 的副本。pyodbc 会话一直持续到游标或连接关闭并且 pyodbc 创建的临时表具有整个会话的范围。
IF OBJECT_ID('tempdb..#TempTable') IS NULL
BEGIN
-- #TempTable gets created here only because SQL Server Management Studio throws errors if it isn't.
CREATE TABLE #TempTable (
int_column int
, name varchar(255)
, datacenter varchar(25)
);
-- This error is thrown so that the stored procedure requires a temporary table created *outside* the stored proc
THROW 50000, '#TempTable table not found in tempdb', 1;
END
ELSE
BEGIN
-- the stored procedure has now validated that the temporary table being used is coming from outside the stored procedure
SELECT * FROM #TempTable;
END;
最后,请注意“tempdb”不是占位符,就像我第一次看到它时所想的那样。“tempdb”是一个实际的 MS SQL Server 数据库系统对象。