web-dev-qa-db-ja.com

作成されたトランザクションの外部からグローバル一時テーブルを検査する方法

SQLのバッチ(トランザクション内で実行される)のデバッグを支援するために、トランザクション内で一部のデータをグローバル一時テーブルにダンプします。グローバル一時テーブルはトランザクション内に作成されます(ここでは説明しないので、選択の余地はありません)。

「with(nolock)」を使用して、トランザクションの外部から(つまり、別の接続の下で)一時テーブルから選択できると思いました。ただし、選択は完了できません。

トランザクションの外部から一時テーブルから選択する方法はありますか?

5
Laurence

「できるからといって、そうする必要があるわけではない」の下にこれを提出する

最初のセッションでバインドトークンを生成し、それを何らかの形で公開すると、別のセッションからトランザクションに参加できます。

たとえば、spid 61から:

if @@TRANCOUNT > 0 rollback
go
begin transaction

select *
into ##t
from sys.objects 


declare @bind_token varchar(255);  
exec sp_getbindtoken @bind_token output
declare @bind_token_bin as varbinary(128) = cast(@bind_token as varbinary(128))
set context_info @bind_token_bin

--rollback

その後、別のセッションから

declare @bind_token varchar(255) = (
    select cast(context_info as varchar(255))
    from sys.dm_exec_sessions
    where session_id = 61
)

exec sp_bindsession @bind_token
go
select * from ##t

いいえ、違います。

作成されたがコミットされていないグローバル一時テーブルは、スキーマ変更ロックによって保護されます。これは、コミットされていない読み取りの分離で必要な最小限のスキーマ安定性ロックを含む、他のすべてのものと 非互換 です。

これが必要な理由を推測するのは難しいですが、通常の問題はグローバル一時テーブルの存続期間に関係しています。これに対する長年の解決策は、プロシージャ内にグローバル一時テーブルを作成することです インスタンスの起動時に実行するようにマークされています 。この方法で作成されたグローバル一時テーブルは、自動的に削除されることはありません。

Azure SQLデータベース(現在はパブリックプレビュー)で、おそらく将来のボックス製品の場合、_ GLOBAL_TEMPORARY_TABLE_AUTODROP 引数がALTER DATABASE SCOPED CONFIGURATIONにあります。

8
Paul White 9

現在のプロセスに小さなコードを追加することが可能である場合、あなたはmightcheatにできるようになります。

_--Demo setup
DROP TABLE IF EXISTS [dbo].[CUSTOMER]
CREATE TABLE [dbo].[CUSTOMER](
    [CustomerID] [int] NOT NULL,
    [FirstName] [varchar](20) NOT NULL,
    [LastName] [varchar](20) NOT NULL,
    [Email] [varchar](30) NOT NULL,
    [PhoneNo] [int] NOT NULL,
    [StreetAddress] [varchar](40) NULL,
    [City] [varchar](20) NULL,
    [OrderID] [int] NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [CustomerID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO


USE [Test]
GO
INSERT [dbo].[CUSTOMER] ([CustomerID], [FirstName], [LastName], [Email], [PhoneNo], [StreetAddress], [City], [OrderID]) VALUES (13579246, N'David', N'Casey', N'[email protected]', 12826363, N'34 Bray Rd', N'Dublin', 94724274)
GO
INSERT [dbo].[CUSTOMER] ([CustomerID], [FirstName], [LastName], [Email], [PhoneNo], [StreetAddress], [City], [OrderID]) VALUES (16579946, N'Donal', N'Smith', N'[email protected]', 13826563, N'78 Ballybrack Rd', N'Dublin', 14724274)
GO
INSERT [dbo].[CUSTOMER] ([CustomerID], [FirstName], [LastName], [Email], [PhoneNo], [StreetAddress], [City], [OrderID]) VALUES (17579946, N'Steve', N'Reidy', N'[email protected]', 13827563, N'22 Conna Rd', N'Cork', 64724274)
GO
INSERT [dbo].[CUSTOMER] ([CustomerID], [FirstName], [LastName], [Email], [PhoneNo], [StreetAddress], [City], [OrderID]) VALUES (18579946, N'Michael', N'Yule', N'[email protected]', 14827563, N'44 Blasket Rd', N'Kilkenny', 44424274)
GO
_

トランザクションの外側で、XMLを保持する新しいテーブルを作成します

_drop table if exists XmlDataTable
CREATE TABLE XmlDataTable (XmlDataColumn xml)
_

次に、トランザクションでグローバル一時テーブルを作成し、そこから選択してxml rawに変換します。次に、その値をXmlDataTableに挿入します。

_begin transaction
drop table if exists ##temp
SELECT * INTO ##temp FROM customer  --This is your normal create for the global temp table

DECLARE @XmlData XML

--select the data from the global temp table as xml raw
SET @XmlData = (SELECT * FROM ##temp FOR XML raw)

--insert that value into LargeVarcharTable
INSERT INTO XmlDataTable VALUES (@XmlData)

--rollback     
_

別のセッションでは、select * from xmldatatable (nolock)を使用して生のxmlを選択できます。

_select * from xmldatatable (nolock)

<row CustomerID="13579246" FirstName="David" LastName="Casey" Email="[email protected]" PhoneNo="12826363" StreetAddress="34 Bray Rd" City="Dublin" OrderID="94724274"/>
<row CustomerID="16579946" FirstName="Donal" LastName="Smith" Email="[email protected]" PhoneNo="13826563" StreetAddress="78 Ballybrack Rd" City="Dublin" OrderID="14724274"/>
<row CustomerID="17579946" FirstName="Steve" LastName="Reidy" Email="[email protected]" PhoneNo="13827563" StreetAddress="22 Conna Rd" City="Cork" OrderID="64724274"/>
<row CustomerID="18579946" FirstName="Michael" LastName="Yule" Email="[email protected]" PhoneNo="14827563" StreetAddress="44 Blasket Rd" City="Kilkenny" OrderID="44424274"/>
_
3
Scott Hodgin