2つのテーブルに値を挿入するために使用するストアドプロシージャがあります。
テーブルには親子関係があります。つまり、最初のテーブルにはID列があり、2番目のテーブルは最初のテーブルを参照します。
次の手順では、Scope_Identity()
値を列として返しています。
ALTER PROCEDURE [dbo].[Insert_Header_Details_Tables]
(
@ProcessID [int]=null,
@FileName [varchar](50)=null,
@VendorName [varchar](250)=null,
@LastName [nvarchar](100)=null,
@FirstName [nvarchar](100)=null,
@isFirstMSH [bit]
)
AS
--BEGIN TRANSACTION
-- Insert into Jobs table
IF(@isFirstMSH = 1)
BEGIN
INSERT INTO LabStagingHeader
([FileName],
[VendorName]
)
VALUES (@FileName,
@VendorName
)
END
-- Retrieve the automatically @ProcID VALUE from the Header table
SET @ProcessID = SCOPE_IDENTITY()
-- Insert new values into LabStagingDetails table
INSERT INTO LabStagingDetails
([ProcessID],
[LastName],
[FirstName]
)
VALUES (@ProcessID,
@LastName,
@FirstName
)
問題は、isFirstMSHがfalseの場合、ProcessID値がNULLです。 isFirstMSH値がfalseの場合、最後に生成された値をテーブルに挿入する必要があります。
プロシージャを複数回呼び出す場合、それらは異なるスコープなので、SCOPE_IDENTITY()
はnull
であると想定されます。そして、概念に注意する必要があります-プロシージャを複数回呼び出す場合、2番目の呼び出しは、「最後に生成された値」がそのプロセスからの前の呼び出しからのものであるか、他のいくつかの同時呼び出しからのものであるかを確認します。同じ手順ですか?
テーブル値パラメーター を検討して、ストアドプロシージャを1回だけ呼び出す必要があるようにします。この呼び出しが「最初の」行を挿入し、複数のユーザーの衝突を心配している場合は追跡を停止できます。 :
_CREATE TYPE dbo.TVPLabStagingDetails AS TABLE
(
FirstName NVARCHAR(100),
LastName NVARCHAR(100)
);
_
これで手順は次のようになります。
_ALTER PROCEDURE dbo.[Insert_Header_Details_Tables]
@FileName [varchar](50) = null,
@VendorName [varchar](250) = null,
@Names dbo.TVPLabStagingDetails READONLY
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.LabStagingHeader([FileName], [VendorName])
SELECT @FileName, @VendorName;
DECLARE @ProcessID INT = SCOPE_IDENTITY();
INSERT dbo.LabStagingDetails([ProcessID], [LastName], [FirstName])
SELECT @ProcessID, LastName, FirstName FROM @Names;
END
_
このような変更が不可能な場合は、差し戻します。それも失敗する場合は、クライアント側が後続の呼び出しで_@ProcessID
_を渡すことができるように、出力パラメーターを使用する必要があります。しかし、実際には、これが最も効率の悪い方法です。
その他のヒント:
SCOPE_IDENTITY、IDENT_CURRENT、および@@ IDENTITYは、ID列に挿入される値を返すため、類似した関数です。テーブルにIDフィールドが定義されていない場合SCOPE_IDENTITYはNULLを返します
BEGIN TRANSACTION;
CREATE TABLE dbo.sample (id INT
PRIMARY KEY IDENTITY(1, 1),
description VARCHAR(20)
);
INSERT INTO dbo.sample
(
--id - column value is auto-generated
description
)
VALUES
(
-- id - int
'sample reg' -- description - varchar
);
SELECT SCOPE_IDENTITY(),
'return SCOPE_IDENTITY';
ROLLBACK TRANSACTION;
GO
BEGIN TRANSACTION;
CREATE TABLE dbo.sample
(id INT
PRIMARY KEY,
description VARCHAR(20)
);
INSERT INTO dbo.sample
(id, -- column value is auto-generated
description
)
VALUES
(20
,-- id - int
'sample reg' -- description - varchar
);
SELECT SCOPE_IDENTITY(),
'null return SCOPE_IDENTITY';
ROLLBACK TRANSACTION;