2010-06-29 15 views
37

Cuando inserta un registro en una tabla con una columna de identidad, puede usar SCOPE_IDENTITY() para obtener ese valor. En el marco de un procedimiento almacenado, lo que sería la forma recomendada para devolver el valor de identidad:Procedimiento almacenado: identidad de devolución como parámetro de salida o escalar

  1. como parámetro de salida SET @RETURN_VALUE = SCOPE_IDENTITY()
  2. Como un escalar SELECT SCOPE_IDENTITY()
  3. Otra forma?

¿Algún pros o contras para cada uno?

Respuesta

33

Todo depende de la capa de acceso a los datos de su cliente. Muchos marcos ORM se basan en consultar explícitamente SCOPE_IDENTITY durante la operación de inserción.

Si tiene un control total sobre la capa de acceso a datos, entonces es sin duda mejor devolver SCOPE_IDENTITY() como un parámetro de salida. Envolver el retorno en un conjunto de resultados agrega sobrecarga de metadatos innecesarios para describir el conjunto de resultados y complica el código para procesar el resultado de las solicitudes.

Si prefiere un retorno conjunto de resultados, a continuación, de nuevo es discutible mejor utilizar la cláusula OUTPUT:

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

De esta manera se puede obtener la fila insertada toda espalda, incluyendo columnas predeterminadas y calculados, y se obtiene un conjunto de resultados que contiene una fila por cada fila insertada, esto funciona correctamente con inserciones por lotes orientadas a conjuntos.

En general, no puedo ver una sola caja al devolver SCOPE_IDENTITY() como resultado, un conjunto sería una buena práctica.

+0

Buen punto al devolver varias filas si hubo varias inserciones. Tal vez Gbn te ganó a eso, pero el tuyo fue más completo. En mi caso particular, no estoy usando un ORM y (por ahora) no insertaré múltiples registros a la vez. –

+1

@Remus: dijiste: "En general, no puedo ver un solo caso al devolver SCOPE_IDENTITY() como resultado el conjunto sería una buena práctica". Entonces, ¿de qué otra forma podría hacerse? ¿Estás implicando que el uso general de SCOPE_IDENTITY() es una mala práctica? ¿En qué sentido, por favor? – Fandango68

+3

@ Fernando68: Estoy diciendo que debería obtenerlo como un parámetro de salida, no como resultado establecer –

3

Prefiero devolver el valor de identidad como un parámetro de salida. El resultado del SP debe indicar si tuvo éxito o no. Un valor de 0 indica que el SP se completó con éxito, un valor distinto de cero indica un error. Además, si alguna vez necesita hacer un cambio y devolver un valor adicional desde el SP, no necesita realizar ningún cambio además de agregar un parámetro de salida adicional.

+0

Por lo que vale, se puede aplicar el mismo razonamiento a la opción 1 o 2, que si necesita agregar otro valor de salida, puede agregar un nuevo parámetro en la opción 1 o agregar otro campo a su seleccione (u otro seleccione si su consumidor lo admite) en la opción 2. Prefiero la opción 1, basada en una suposición infundada de que requiere menos "gastos generales" por parte de la base de datos y/o del cliente. –

+0

Estoy con jmgant en esto. No es tan difícil "SELECCIONAR" una columna adicional. Sé que puede hacer que los parámetros de entrada sean opcionales (con un valor predeterminado); ¿qué pasa con los parámetros de salida? Si no puede, es más fácil hacer cambios en el 'SELECCIONAR' ya que probablemente ignorará la columna adicional a menos que lo necesite. A pesar de eso, creo que el parámetro de salida es el camino "correcto" sin la sobrecarga de un conjunto de resultados. –

38

Otra opción sería como el valor de retorno para el procedimiento almacenado (esto no lo sugiero, ya que generalmente es mejor para los valores de error).

Lo he incluido como ambos cuando está insertando una sola fila en casos en que el procedimiento almacenado estaba siendo consumido por otros procedimientos de SQL y un front-end que no podría funcionar con los parámetros OUTPUT (IBATIS en .NET I creer):

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 

El parámetro de salida es más fácil trabajar con en T-SQL cuando se llama desde otros procedimientos almacenados OMI, pero algunos lenguajes de programación tienen poca o ninguna ayuda para los parámetros de salida y trabajar mejor con conjuntos de resultados.

+0

Buen ejemplo de ambas maneras de hacerlo, aunque no creo que haga ambas cosas al mismo tiempo, a menos que tenga una razón sólida para creer que ambas son necesarias, por ejemplo, si no tuviera idea de qué idioma consumiría mi procesador y sabía que necesitaba apoyar ambos métodos. –

+0

cierto. No debería haber dicho, "por lo general". He usado ambos métodos en un entorno donde necesitábamos acceso a ambas formas de producción. Reescribiré mi respuesta. –

1

O bien como conjunto de registros o parámetro de salida. Este último tiene menos sobrecarga y yo tendería a usar ese conjunto de registros en lugar de solo una columna/fila.

Si esperaba> 1 fila que haría uso de la cláusula de salida y un conjunto de registros

Valores de retorno normalmente se utilizan para el tratamiento de errores.

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

Por favor edite con más información. Las respuestas de solo código y "prueba esto" están [desaconsejadas] (http://meta.stackexchange.com/questions/196187/is-try-this-bad-practice), porque no contienen contenido que se pueda buscar y no lo hacen. explicar por qué alguien debería "probar esto". –

Cuestiones relacionadas