私はこれと同じ問題を抱えていましたが、ここでの答えはどれもそれを修正しませんでした。「SET NOCOUNT ON」を機能させることができませんでした。また、テーブル変数を操作する単一のバッチ操作を行うこともできませんでした。うまくいったのは、一時テーブルを 2 つのバッチで使用することでしたが、正しい構文を見つけるのに一日中かかりました。次のコードは、最初のバッチで一時テーブルを作成してデータを設定し、次に 2 番目のバッチで、ストアド プロシージャ名の前に 2 つのドットを付けたデータベース名を使用してストアド プロシージャを実行します。この構文は、「ストアド プロシージャ '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 データベース システム オブジェクトです。