набор результатов на основе успеха или неудачи - PullRequest
0 голосов
/ 12 апреля 2009

У меня есть хранимая процедура, которая возвращает два набора результатов в зависимости от успеха или неудачи.

Набор результатов успешного выполнения SP: имя, идентификатор, ошибка, desc
Результат ошибки SP sret: error, desc

Я использую следующий запрос, чтобы получить результат хранимой процедуры. Возвращает 0 для успеха и -1 для ошибки.

declare @ret int

DECLARE @tmp TABLE (
     name  char(70),
     id    int,
     error char(2),
     desc  varchar(30)
)

insert into @tmp
EXEC @ret  = sptest '100','King'

select @ret

select * from @tmp

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

Ответы [ 4 ]

1 голос
/ 12 апреля 2009

Вы не можете вернуть 2 разных набора записей и загрузить одну и ту же временную таблицу. Никто не может попытаться заполнить 2 разные таблицы.

Есть 2 варианта.

  1. Измените свой сохраненный процесс

    • Все 4 столбца возвращаются при любых условиях
    • 1-я пара (имя, идентификатор) столбцы имеют значение NULL при ошибке
    • 2-я пара (ошибка, desc) равна NULL в случае успеха
  2. Если вы используете SQL Server 2005, используйте TRY / CATCH, чтобы разделить пути успешного и неудачного кода. Приведенный ниже код основывается на использовании новой обработки ошибок для передачи результата ошибки через исключение / RAISERROR.

* * 1 022 Пример: * 1 023 *
CREATE PROC sptest
AS
DECLARE @errmsg varchar(2000)

BEGIN TRY
   do stuff
   SELECT col1, col2, col3, col4 FROM table etc
   --do more stuff
END TRY
BEGIN CATCH
   SELECT @errmsg = ERROR_MESSAGE()
   RAISERROR ('Oops! %s', 16, 1, @errmsg)
END CATCH
GO

DECLARE @tmp TABLE ( name CHAR(70), id INT, error char(2), desc varchar(30)

BEGIN TRY
    insert into @tmp
    EXEC sptest '100','King'
    select * from @tmp
END TRY
BEGIN CATCH
   PRINT ERROR_MESSAGE()
END CATCH
0 голосов
/ 28 мая 2009

Вы не можете сделать это с помощью одного звонка. Вам придется вызвать его один раз, либо получить статус возврата, а затем перейти в зависимости от состояния к команде INSERT..EXEC, которая будет работать для числа возвращаемых столбцов, или вызвать его один раз, при условии успеха, с TRY. .CATCH, а затем в Catch вызовите его снова, предполагая, что он потерпит неудачу (как он попал в CATCH).

Еще лучше было бы либо переписать хранимую процедуру, чтобы она возвращала согласованный набор столбцов, либо написать собственную хранимую процедуру, табличную функцию или запрос, извлекая код из этой хранимой процедуры и адаптируя ее к вашему использованию. Это правильный ответ в SQL.

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

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

DECLARE @tmp TABLE (
 name  char(70) null,
 id    int null,
 error char(2),
 desc  varchar(30)

)

Надеюсь, это поможет,

Bill

0 голосов
/ 12 апреля 2009

Моя вина !! Был слишком быстр в ответе. Вам нужно только опираться на возвращаемое значение, поэтому построение логики против него намного лучше.

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

declare @ret int

DECLARE @tmp TABLE (name CHAR(70), id INT, error char(2), desc varchar(30))
DECLARE @tmperror TABLE (error char(2), desc varchar(30))


EXEC @ret = sptest '100','King'

IF @ret != 0
BEGIN
  INSERT INTO @tmperror
  EXEC sptest '100','King';
  SELECT * FROM @tmperror;
END
ELSE
BEGIN
  INSERT INTO @tmp
  EXEC sptest '100','King';
  SELECT * FROM @tmp;
END

Помните, что это решение не оптимально.

...