2010-06-29 3 views
37

Когда вы вставляете запись в таблицу с столбцом идентификации, вы можете использовать SCOPE_IDENTITY() для получения этого значения. В контексте хранимой процедуры, которая была бы рекомендуемым способом вернуть значение идентичности:Сохраненная процедура - возвращает идентификатор в качестве выходного параметра или скаляра

  1. В качестве выходного параметра SET @RETURN_VALUE = SCOPE_IDENTITY()
  2. В скалярной SELECT SCOPE_IDENTITY()
  3. Другим способом?

Любые плюсы и минусы каждого?

ответ

33

Все зависит от вашего клиентского доступа к данным. Многие рамки ORM полагаются на явный запрос SCOPE_IDENTITY во время операции вставки.

Если вы полностью контролируете уровень доступа к данным, возможно, лучше вернуть SCOPE_IDENTITY() в качестве выходного параметра. Обертка возврата в результирующем наборе добавляет лишние метаданные для описания набора результатов и усложняет код для обработки результата запроса.

Если вы предпочитаете набор результатов возврата, то снова спорно лучше использовать предложение OUTPUT:

INSERT INTO MyTable (col1, col2, col3) 
OUTPUT INSERTED.id, col1, col2, col3 
VALUES (@col1, @col2, @col3); 

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

В целом, я не вижу ни одного случая при возврате SCOPE_IDENTITY(), так как результат был бы хорошей практикой.

+0

Хорошая точка при возврате нескольких строк, если было несколько вставок. Может быть, gbn избил вас до этого, но ваш был более тщательным. В моем конкретном случае я не использую ORM и (пока) не будет вставлять сразу несколько записей. –

+1

@Remus: вы сказали: «В общем, я не вижу ни одного случая при возвращении SCOPE_IDENTITY(), поскольку результирующий набор будет хорошей практикой». Тогда как еще это можно сделать? Вы подразумеваете, что общее использование SCOPE_IDENTITY() - это плохая практика? В каком смысле, пожалуйста? – Fandango68

+3

@ Fernando68: Я говорю, что вы должны получить его как выходной параметр, а не как результат –

3

Я предпочитаю возвращать значение идентификатора в качестве выходного параметра. Результат SP должен указывать, удалось ли это или нет. Значение 0 указывает, что SP успешно завершен, ненулевое значение указывает на ошибку. Кроме того, если вам когда-либо понадобится внести изменения и вернуть дополнительное значение из SP, вам не нужно вносить какие-либо изменения, кроме добавления дополнительного выходного параметра.

+0

Для чего это стоит, то же рассуждение можно применить к любому варианту 1 или 2, что, если вам нужно добавить другое значение выходного сигнала, можно либо добавить новый параметр в соответствии с вариантом 1 или добавить еще одно поле для вашего выберите (или другой вариант, если ваш потребитель поддерживает его) в соответствии с вариантом 2. Я предпочитаю вариант 1 самостоятельно, основываясь на необоснованном предположении, что он требует меньше «накладных расходов» со стороны базы данных и/или клиента. –

+0

Я с jmgant на этом. Не так сложно «ВЫБРАТЬ» дополнительный столбец. Я знаю, что вы можете сделать входные параметры опционными (со значением по умолчанию); как насчет выходных параметров? Если вы не можете, легче внести изменения в 'SELECT', так как вы, вероятно, проигнорируете дополнительный столбец, если это вам не понадобится. Несмотря на это, я думаю, что выходной параметр является «правильным» способом без накладных расходов результирующего набора. –

38

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

Я включил его как в том случае, когда он вставлял одну строку в случаях, когда хранимая процедура использовалась как другими процедурами SQL, так и интерфейсом, который не мог работать с параметрами OUTPUT (IBATIS в .NET I верить):

CREATE PROCEDURE My_Insert 
    @col1   VARCHAR(20), 
    @new_identity INT OUTPUT 
AS 
BEGIN 
    SET NOCOUNT ON 

    INSERT INTO My_Table (col1) 
    VALUES (@col1) 

    SELECT @new_identity = SCOPE_IDENTITY() 

    SELECT @new_identity AS id 

    RETURN 
END 

выходной параметр легче работать в T-SQL при вызове из других хранимых процедур ИМО, но некоторые языки программирования имеют плохое или нет поддержки для выходных параметров и лучше работать с наборами результатов.

+0

Хороший пример обоих способов сделать это, хотя я не думаю, что я буду делать оба в одно и то же время, если у меня не будет веских оснований полагать, что оба нужны, например, если бы я понятия не имел, какой язык будет потреблять мою процедуру и знал, что необходимо поддерживать оба метода. –

+0

Правда. Я не должен был говорить «обычно». Я использовал оба метода в среде, где нам нужен доступ к обеим формам вывода. Я изменю свой ответ. –

1

Либо как набор записей, либо выходной параметр. У последнего меньше накладных расходов, и я бы использовал его, а не один набор записей столбцов/строк.

Если я ожидал> 1 ряд я бы использовать предложение OUTPUT и записи

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

1
SELECT IDENT_CURRENT('databasename.dbo.tablename') AS your identity column; 
+3

Пожалуйста, отредактируйте с дополнительной информацией. Только код и «попробуйте» ответы [обескуражены] (http://meta.stackexchange.com/questions/196187/is-try-this-bad-practice), поскольку они не содержат содержимого, доступного для поиска, и не объясните, почему кто-то должен «попробовать это». –