Как вы пишете рекурсивную хранимую процедуру - PullRequest
0 голосов
/ 28 мая 2010

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

Редактировать

Теперь у меня есть следующее предложение (заметьте, у меня уже есть столбец идентификаторов, мне нужен дополнительный столбец идентификаторов.

ALTER PROCEDURE [dbo].[DataInstance_Insert] 
    @DataContainerId int out,
    @ModelEntityId int,
    @ParentDataContainerId int, 
    @DataInstanceId int out
AS
BEGIN

    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    WHILE (@DataContainerId is null) 
        EXEC DataContainer_Insert @ModelEntityId, @ParentDataContainerId, @DataContainerId output   

    INSERT INTO DataInstance (DataContainerId, ModelEntityId)
    VALUES (@DataContainerId, @ModelEntityId)   

    SELECT @DataInstanceId = scope_identity()                       
END    

    ALTER PROCEDURE [dbo].[DataContainer_Insert]
        @ModelEntityId int,
        @ParentDataContainerId int,
        @DataContainerId int out
    AS
    BEGIN 
    BEGIN TRY
        SET NOCOUNT ON;
        DECLARE @ReferenceId int

        SELECT @ReferenceId = isnull(Max(ReferenceId)+1,1) from DataContainer Where ModelEntityId=@ModelEntityId

        INSERT INTO DataContainer (ReferenceId, ModelEntityId, ParentDataContainerId)
        VALUES (@ReferenceId, @ModelEntityId, @ParentDataContainerId)

        SELECT @DataContainerId = scope_identity()
    END TRY
    BEGIN CATCH
    END CATCH
    END

Ответы [ 4 ]

2 голосов
/ 28 мая 2010
  1. В блоках CATCH вы должны проверить значение XACT_STATE. Вы можете быть в обреченной транзакции (-1), и в этом случае вы вынуждены выполнить откат. Или ваша транзакция может иметь уже откат, и вы не должны продолжать работать в предположении существующей транзакции. Процедуру шаблона, которая обрабатывает исключения T-SQL, попробуйте / перехватите blcoks и транзакции, см. Обработка исключений и вложенные транзакции
  2. Никогда, ни при каких языках не делайте рекурсивные вызовы в блоках исключений. Вы не проверяете , почему вы нажали исключение, поэтому вы не знаете, можно ли попробовать еще раз. Что если исключение составляет 652, файловая группа только для чтения? Или ваша база данных в максимальном размере? Вы будете проклинать, пока не нажмете на переполнение стека ...
  3. Код, который читает значение, принимает решение на основе этого значения, а затем записывает что-то, всегда может потерпеть неудачу при одновременном использовании, если не будет должной защиты Вам необходимо обернуть SELECT и INSERT в транзакцию, и ваш SELECT должен быть в СЕРЬЕЗНОМ УРОВНЕ изоляции.

И, наконец, игнорируя явно неверный код в вашем посте, вот как вы вызываете хранимую процедуру, передавая аргументы OUTPUT:

exec DataContainer_Insert  @SomeData, @DataContainerId OUTPUT;
1 голос
/ 28 мая 2010

Еще лучше, почему бы не сделать UserID столбцом идентификаторов, а не пытаться повторно реализовать столбец идентификаторов вручную?

Кстати: я думаю, что вы имели в виду

VALUES (@DataContainerId + 1 , SomeData)
1 голос
/ 28 мая 2010

Почему бы не использовать:

 NewId() 

T SQL функция? (предполагается, что SQL Server 2005/2008)

0 голосов
/ 28 мая 2010

что sp никогда не выполнит успешную вставку, у вас есть свойство identity в таблице DataContainer, но вы вставляете ID, в этом случае вам нужно будет установить identity_insert, но тогда scope_identity () не будет работать *

Нарушение PK также может не отслеживаться, поэтому вам также может понадобиться проверить XACT_STATE ()

почему вы возитесь с max, используйте scope_identity () и покончите с этим

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