从表中检索自动递增的列值,其中在单个存储过程中多次插入/选择

时间:2009-05-29 13:40:26

标签: sql sql-server stored-procedures

我有一个带有多个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

这显然不起作用。这是我试图解决这个问题。我对SQL很新,所以对此问题的任何帮助都将非常感激。

6 个答案:

答案 0 :(得分:7)

在插入后使用scope_identity()来捕获当前范围内的最新单一标识值:

DECLARE @ID     int


INSERT ......
SELECT @ID=scope_identity()

在任何需要的地方使用@ID

注意:SCOPE_IDENTITY()优先于较旧的@@ IDENTITY,因为它提供了当前范围中的最后一个Identity值,这避免了插入日志表(带有标识)的触发器的问题。

但是,如果您需要多个标识值(插入一组行),请使用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

输出:

(5 row(s) affected)
RowID
-----------
1
2
3
4
5

(5 row(s) affected)

答案 1 :(得分:2)

用于MS Sql Server

无论何时插入记录并且它具有自动增量列(ms-sql用语中的标识列),您都可以使用它来检索您插入的行的ID:

@id = SCOPE_IDENTITY()

这可确保您获得插件生成的标识列值,而不是其他用户在您的代码运行期间(插入和通过 scope_identity()获取标识之间)

答案 2 :(得分:2)

哎呀......你的交易和交易都被扭曲了......

您希望这两个插入在同一事务中发生(我从原始proc中间的COMMIT语句中推断出)。因此,您需要在所有BEGIN TRANSACTIONCOMMIT语句周围放置INSERTSELECT语句,以隔离数据更改。

请考虑以下事项:

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

答案 3 :(得分:1)

也不在事务中间提交,如果一个插入失败,您希望两个插入都回滚。在线阅读有关交易处理的书籍。

答案 4 :(得分:1)

我们可以返回标识列,如:

SELECT @@identity as 'Identity'

并在以下代码中读取此标识值:

int ID = Convert.ToInt32(cmdinsert.ExecuteScalar());

答案 5 :(得分:0)

您可以使用@@ Identity全局变量来检索上次插入的标识值

SELECT @ManagerId=@@Identity

您还可以使用Scope_Identity和IDENT_Current函数