Получение значения автоинкрементного столбца из таблицы, в которой несколько вставок / выборок в одной хранимой процедуре - PullRequest
5 голосов
/ 29 мая 2009

У меня есть хранимая процедура с несколькими операторами вставки / выбора. Допустим, я использую первую вставку для заполнения таблицы «Менеджер». При вставке добавляется ManagerId (увеличивается автоматически), но на него нет ссылки в операторе вставки. Затем я хочу использовать 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 ]

7 голосов
/ 29 мая 2009

используйте 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)
2 голосов
/ 29 мая 2009

Тьфу ... твой прок и транзакция все перепутаны ...

Вы хотите, чтобы эти две вставки происходили в одной и той же транзакции (которую я вывел из оператора COMMIT в середине вашего исходного процесса). Поэтому вам необходимо соответствующим образом разместить операторы BEGIN TRANSACTION и COMMIT вокруг всех ваших операторов INSERT и SELECT, чтобы изолировать изменение данных.

Рассмотрим следующее:

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
2 голосов
/ 29 мая 2009

для MS Sql Server

Всякий раз, когда вы вставляете запись, в которой есть столбец автоинкремента (столбец идентификаторов на языке ms-sql), вы можете использовать его для получения идентификатора вставленной строки:

@id = SCOPE_IDENTITY()

это гарантирует, что вы получите значение столбца идентификатора, созданное вашей вставкой, а не другими пользователями во время выполнения кода (между вставкой и получением идентификатора с помощью scope_identity () )

1 голос
/ 21 января 2010

Мы можем вернуть идентификационный столбец как:

SELECT @@identity as 'Identity'

и прочитайте это значение в виде кода:

int ID = Convert.ToInt32(cmdinsert.ExecuteScalar());
1 голос
/ 30 мая 2009

Также не выполняйте фиксацию в середине транзакции, вы хотите, чтобы обе вставки откатывались в случае неудачи. Читайте в Книгах онлайн об обработке транзакций.

0 голосов
/ 29 мая 2009

Вы можете использовать глобальную переменную @@ Identity для получения последнего введенного значения идентификатора

SELECT @ManagerId=@@Identity

вы также можете использовать функции Scope_Identity и IDENT_Current

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...