I have a stored procedure with multiple insert/select statements. Let's say I'm using the first insert to populate a "Manager" table. On insert, a ManagerId (incremented automatically) is added, but not referenced in the insert statement. I then wish to use the ManagerId from this table to insert a row into another table, where ManagerId is a foreign key. Sample code as follows..
我有一個包含多個insert / select語句的存儲過程。假設我正在使用第一個插入來填充“Manager”表。在插入時,添加了ManagerId(自動遞增),但未在insert語句中引用。然后,我希望使用此表中的ManagerId將行插入另一個表,其中ManagerId是外鍵。示例代碼如下..
USE [TEST]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sptInsertNewManager]
-- Add the parameters for the stored procedure here
@FName varchar(50),
@LName varchar(50),
@EMail varchar(100),
@UserRoleID int,
@LANUserID varchar(25),
@GroupID int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO [Manager]
([FName],
[LName],
[Email],
[UserRoleID],
[LANUserID],
[ActiveFlag],
[GroupID]
)
VALUES
(@FName
,@LName
,@EMail
,@UserRoleID
,@LANUserID
,1
,@GroupID);
COMMIT
SELECT ManagerId FROM [Manager] AS newManager WHERE LANUserID = @LANUserID;
--also insert into Users table.
INSERT INTO [dbo].[aspnet_Users] (
[UserId],
[UserName],
[LoweredUserName],
[ManagerId]
)
VALUES (
NEWID(),
@LANUserID,
LOWER(@LANUserID),
newManager)
END
This, obviously, does not work. This was my attempt at solving this. I'm fairly new to SQL, so any help with this problem would be greatly appreciated.
顯然,這不起作用。這是我試圖解決這個問題。我對SQL很新,所以對此問題的任何幫助都將非常感激。
7
use scope_identity() after your insert to capture the most recent single identity value from within your current scope:
在插入后使用scope_identity()從當前范圍內捕獲最新的單個標識值:
DECLARE @ID int
INSERT ......
SELECT @ID=scope_identity()
use @ID wherever you need it
在任何需要的地方使用@ID
note: SCOPE_IDENTITY() is preferred over the older @@IDENTITY because it gives the last Identity value in the current scope, which avoids issues from triggers that insert into log tables (with identities).
注意:SCOPE_IDENTITY()優先於舊的@@ IDENTITY,因為它提供了當前范圍中的最后一個Identity值,這避免了插入日志表(帶有標識)的觸發器的問題。
However, if you need multiple identity values (inserting a set of rows), use OUTPUT and INTO:
但是,如果您需要多個標識值(插入一組行),請使用OUTPUT和INTO:
declare @test table (RowID int identity(1,1) primary key not null, RowValue varchar(10) null)
declare @OutputTable table (RowID int not null)
insert into @test (RowValue)
OUTPUT INSERTED.RowID
INTO @OutputTable
SELECT 'A'
UNION SELECT 'B'
UNION SELECT 'C'
UNION SELECT 'D'
UNION SELECT 'E'
select * from @OutputTable
the output:
輸出:
(5 row(s) affected)
RowID
-----------
1
2
3
4
5
(5 row(s) affected)
2
for MS Sql Server
對於MS Sql Server
Whenever you insert a record and it has auto-increment column (Identity Column in ms-sql parlance) you can user this to retrieve the id for the row you inserted:
無論何時插入記錄並且它具有自動增量列(ms-sql用語中的標識列),您都可以使用它來檢索您插入的行的ID:
@id = SCOPE_IDENTITY()
this ensures that you get the identity column value that your insert produced, not by the other users during the time your code was running (between insert and getting identity by scope_identity())
這可以確保您獲得插件生成的標識列值,而不是其他用戶在您的代碼運行期間(插入和通過scope_identity()獲取標識之間)
2
Yuck... you have your proc and transaction all twisted up...
哎呀......你的交易和交易都被扭曲了......
You want these two inserts to occur within the same transaction (which I am deducing from the COMMIT
statement in the middle of your original proc). So you need to appropriately place a BEGIN TRANSACTION
and COMMIT
statement around all of your INSERT
and SELECT
statements to isolate the data change.
您希望這兩個插入在同一事務中發生(我從原始proc中間的COMMIT語句中推斷出)。因此,您需要在所有INSERT和SELECT語句周圍放置一個BEGIN TRANSACTION和COMMIT語句,以隔離數據更改。
Consider the following:
考慮以下:
CREATE PROCEDURE [dbo].[sptInsertNewManager]
-- Add the parameters for the stored procedure here
@FName varchar(50),
@LName varchar(50),
@EMail varchar(100),
@UserRoleID int,
@LANUserID varchar(25),
@GroupID int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @ManagerID INT
BEGIN TRANSACTION
-- Insert statements for procedure here
INSERT INTO [Manager]
([FName],
[LName],
[Email],
[UserRoleID],
[LANUserID],
[ActiveFlag],
[GroupID]
)
VALUES
(@FName
,@LName
,@EMail
,@UserRoleID
,@LANUserID
,1
,@GroupID);
-- Collect the ID you just created
SELECT @ManagerID = SCOPE_IDENTITY()
--also insert into Users table.
INSERT INTO [dbo].[aspnet_Users] (
[UserId],
[UserName],
[LoweredUserName],
[ManagerId]
)
VALUES (
NEWID(),
@LANUserID,
LOWER(@LANUserID),
@ManagerID) -- This is the new identity you just created
COMMIT
END
1
ALso do not commit in the middle of the transaction, you want both inserts to rollback if one fails. Read in Books online about transaction processing.
也不要在事務中間提交,如果一個插入失敗,您希望兩個插入都回滾。在線閱讀有關交易處理的書籍。
1
We can return the identity column like:
我們可以返回標識列,如:
SELECT @@identity as 'Identity'
and read this identity value in code like:
並在代碼中讀取此標識值,如:
int ID = Convert.ToInt32(cmdinsert.ExecuteScalar());
0
You can use @@Identity global variable to retrieve last inserted identity value
您可以使用@@ Identity全局變量來檢索上次插入的標識值
SELECT @ManagerId=@@Identity
you can also use Scope_Identity and IDENT_Current functions
您還可以使用Scope_Identity和IDENT_Current函數
本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2009/05/29/658ec75f7f33e94674997ead71cb3448.html。