Сохранение числового возвращаемого значения хранимой процедуры SQL Server в переменной приводит к тому, что указанная переменная всегда равна нулю - PullRequest
0 голосов
/ 14 мая 2019

Простая хранимая процедура и простой вызов в SQL Server 2014:

CREATE TABLE [dbo].[SEQUENCES]
(
    [SEQ_NAME] [nvarchar](50) NOT NULL,
    [SEQ_NEXT_ID] [numeric](11, 0) NOT NULL,
    [SEQ_INCREMENT] [numeric](2, 0) NOT NULL,

    CONSTRAINT [SEQ_PK] 
        PRIMARY KEY CLUSTERED ([SEQ_NAME] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE PROCEDURE [dbo].[SomeStoredProcedure]
    @SequenceName [NVARCHAR](MAX),
    @Increment [INT]
AS
BEGIN
    UPDATE [dbo].[SEQUENCES]
    SET SEQ_NEXT_ID = SEQ_NEXT_ID + @Increment
    OUTPUT deleted.SEQ_NEXT_ID
    WHERE SEQ_NAME = @SequenceName
END

BEGIN
    DECLARE @value NUMERIC(11,0);

    EXEC @value = SomeStoredProcedure 'FOO', 1;  -- 'FOO' already exists in SEQUENCES so we do get a value

    -- weird results    this always prints 0     if we uncomment the return
    -- statement right below then and only then the correct value is printed
    PRINT @value;
    -- RETURN;

    INSERT INTO SOME_TABLE (ID, NAME) 
    VALUES (@value, -- @value is always zero so we get a PK constraint violation ...
            'Something');
END

Значение, которое получает @value, всегда равно нулю, и из-за этого мы получаем нарушение ограничения PK в операторе обновления:

Сообщение 2627, Уровень 14, Состояние 1, Линия ...
Нарушение ограничения PRIMARY KEY 'PK'. Невозможно вставить повторяющийся ключ в объект 'dbo.SOME_TABLE'. Значение дубликата ключа (0).

Если мы раскомментируем оператор return в середине блока, то и только тогда оператор PRINT выводит правильное значение. Должно быть, упущено что-то действительно очевидное, но что?

Ответы [ 3 ]

3 голосов
/ 14 мая 2019

Если вы хотите вернуть некоторые значения из хранимой процедуры, вам нужно использовать параметры OUTPUT.

Например, создать процедуру, такую ​​как

CREATE PROCEDURE [dbo].[SomeStoredProcedure]
   @SequenceName [nvarchar](max),
   @Increment [int],
   @Value int OUTPUT

, а затем присвоить правильное значение параметру @Value.

Чтобы прочитать значение, возвращенное из хранимой процедуры, используйте:

EXEC [dbo].[SomeStoredProcedure] 'FOO', 1, @Value = @Value OUTPUT;

Значение 0 после EXEC @value = SomeStoredProcedure 'FOO', 1; означает, что хранимая процедура не вернула ошибок.

2 голосов
/ 14 мая 2019

Две вещи, которые вам нужно сделать: 1. Добавьте выходной параметр.

  ALTER PROCEDURE [dbo].[SomeStoredProcedure]
       @SequenceName [nvarchar](max),
       @Increment [int],
       @NextId numeric(11, 0) OUTPUT
   AS
   BEGIN
         DECLARE  @nextIds TABLE (id NUMERIC(11, 0));

         UPDATE   [dbo].[SEQUENCES]
         SET      SEQ_NEXT_ID = SEQ_NEXT_ID + @Increment
         OUTPUT   DELETED.SEQ_NEXT_ID INTO @nextIds
         WHERE    SEQ_NAME    = @SequenceName;

         SET @NextId = (SELECT id FROM @nextIds);
   END
  1. Получить выходное значение из хранимой процедуры.

    BEGIN
      DECLARE   @value           NUMERIC(11,0);
    
      EXECUTE SomeStoredProcedure 'FOO', 1, @value OUTPUT;  -- 'FOO' already exists in SEQUENCES so we do get a value
    
      -- weird results    this always prints 0     if we uncomment the return
      -- statement right below then and only then the correct value is printed
      --select @value;
      -- RETURN;
    
      INSERT INTO SOME_TABLE (ID,NAME) 
      VALUES ( @value, -- @value is always zero so we get a PK constraint violation ...
      'Something');
    END
    
0 голосов
/ 14 мая 2019

Ваш процесс ничего не возвращает.Нет параметра OUTPUT, который я вижу.Хуже того, вы вызываете код, предполагая, что proc вернет строку.Procs возвращает целые числа (коды возврата).

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