前提
・RDBMSは「SQL Server 2019」
・2つ(2種類)のストアドで同じ名前の一時テーブルを定義し、使用している。
・2つのストアドは同時に実行されることがある。
・2つのストアドは別コネクション(接続)から実行される。
発生していること・実現したいこと
2つのストアドが同時に実行された場合に、
一方のストアドで共通の名前の一時テーブルをTRUNCATEした際に、以下のエラーが発生する。
エラーの原因をご教示お願いいたします。
エラーメッセージ
コード:3930 説明:「現在のトランザクションはコミットできず、ログファイルに書き込む操作をサポートできません。トランザクションをロールバックしてください。」
試したこと
・2つのストアドの実行時に、定義している一時テーブルのオブジェクトID・オブジェクト名を確認ところ参照してる一時テーブルは異なってることを確認した。
補足
一時テーブルの定義
-- 一時テーブルを定義 IF OBJECT_ID(N'tempdb..#wIo', N'U') IS NULL CREATE TABLE #wIo ( Deleted NUMERIC(1,0) DEFAULT ((0)), IoDocNo NUMERIC(22,0), IoRecNo NUMERIC(22,0), IoDate CHAR(10) COLLATE DATABASE_DEFAULT, IoType CHAR(2) COLLATE DATABASE_DEFAULT, ・ ・ ・ ); TRUNCATE TABLE #wIo;
-- 一時テーブルを定義 IF OBJECT_ID(N'tempdb..#wIo', N'U') IS NULL CREATE TABLE #wIo ( Deleted NUMERIC(1,0) DEFAULT ((0)), IoDocNo NUMERIC(22,0), IoRecNo NUMERIC(22,0), IoDate CHAR(10) COLLATE DATABASE_DEFAULT, IoType CHAR(2) COLLATE DATABASE_DEFAULT, ・ ・ ・ ); TRUNCATE TABLE #wIo;
※発生していることに記載している、「一方のストアドで共通の名前の一時テーブルをTRUNCATEした際に、以下のエラーが発生する。」は↑のTRUNCATE分ではありません。ストアドの中で別ストアドを呼び出し↑の一時テーブルをTRUNCATEしています。
その一時テーブルの定義を質問に追記して下さい
# を2つつけてグローバルな一時テーブルになっているのでは?
成程。
では、実際に実行している内容が情報としてあった方が良いですね。
一時テーブルの定義を追加いたしました。
単体で動かすと問題がないが、同時に実行するとエラーが発生するということでしょうか?
「TRUNCATE TABLE は、トランザクション内で実行できません。」という記述がありますが、それはクリアできていますか?
https://docs.microsoft.com/ja-jp/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-ver16
あー、これ Azure Synapse Analytics と Analytics Platform System (PDW) での話ですね。失礼しました。
はい。単体では問題ないですが同時に実行されるとエラーが発生します。
DELETE にすると問題ないでしょうか?
DELETE でも同様です。
(仮にSELECTにしてみるとエラーは発生しませんでしたが一時テーブルの内容を更新するような操作はエラーになることを確認しました。(TRUNCATE,DELETE,INSERT))
なにかおかしいですね。
存在チェックをやめて必ずテーブルを作成するようにしたらどうなります?
存在チェックをコメントアウトして必ずテーブルを作成するようにして動作確認しましたが
同様のエラーとなりました。
CREATE したストアドと TRUNCATE しているストアドが別ってことですか?
呼び出したストアドは一時テーブルがどのような構造をしているのかわかりません。
かなり変則的な使い方だと思います。
一時表はCREATE したストアドの中だけで使用し、DROP して抜けないと収集がつかなくなります。
はい、そうなのです。
ストアド①のパラメータによって呼び出すストアドを分けてるようなイメージで、その呼び出された先でストアド①でCREATEされた一時テーブルに対してデータを登録し、さらにその一時テーブルを使用しマスタ・トランテーブルなどへ登録するようなフローです。
「一時表はCREATE したストアドの中だけで使用し、DROP して抜けないと収集がつかなくなります。」
↑この収集がつかないというのは、呼び出し先で意図した一時テーブルを参照できる保証がないということでしょうか?
質問は修正できます。
全角空白が入っていてエラーになりませんか?
> IoDate □□CHAR(10) COLLATE DATABASE_DEFAULT,
> IoType □□□CHAR(2) COLLATE DATABASE_DEFAULT,
すみません。
質問にソース貼り付けたらインデントがずれたので全角空白入れて調節しました。
実際のソースには含まれていません。
>↑この収集がつかないというのは、呼び出し先で意図した一時テーブルを参照できる保証がないということでしょうか?
ストアドが増えていくと、どこでどのような一時テーブルを使っているか把握できなくなってしまい、ストアドから他のストアドを気軽に呼び出せなくなってしまう、ということです。
https://sql55.com/column/temporary-tables-with-same-name.php
の後ろのほうに書かれていますが、別のストアドで同じ名前の一時表を作ってしまった場合、どちらが使われるかは保証されないようです。
