¿Por qué @@ IDENTITY o SCOPE_IDENTITY () sería DBNull?
Pregunta
(resuelto: ver abajo)
Tengo el siguiente fragmento de código:
Protected Sub SqlDataSource1_Inserted(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.SqlDataSourceStatusEventArgs)
Handles SqlDataSource1.Inserted
affected = CInt(DirectCast(e.Command.Parameters("@affected"), IDbDataParameter).Value)
newID = CInt(DirectCast(e.Command.Parameters("@newID"), IDbDataParameter).Value)
End Sub
Donde @newID se define así en la cadena SQL:
"INSERT INTO x(a,b,c) VALUES (@a,@b,@c); SELECT @affected = @@rowcount, @newID = SCOPE_IDENTITY();
Los parámetros se definen usando ASP.NET de la siguiente manera:
Lo extraño es que esto funciona el 90% del tiempo, pero de vez en cuando arroja una InvalidCastException que dice que "La conversión del tipo 'DBNull' al tipo 'Integer' no es válida". ¿Alguna idea sobre qué podría estar causando que este valor sea nulo? No tengo ningún activador establecido en la tabla, y lo único que está haciendo mi consulta es ejecutar una inserción simple en 1 tabla.
Editar : según las sugerencias aquí, agregué un parámetro afectado
. Establecí un punto de interrupción y afecté = 1, pero aún obtuve la excepción. Sin embargo, descubrí que tenía SELECT @newID antes de SELECT @affected. Cambié el orden y ahora @affected = 0. Entonces parece ser un problema con mi declaración de inserción después de todo. ¡Gracias por tu ayuda!
Solución
De MSDN
Después de INSERTAR, SELECCIONAR EN, o en masa se completa la declaración de copia, @@ IDENTITY contiene la última identidad valor generado por el declaración. Si la declaración no lo hizo afectar cualquier tabla con identidad columnas, @@ IDENTITY devuelve NULL.
¿Tiene una comprobación para ver si la inserción ha sido exitosa? Es posible que el registro que está intentando insertar no pueda insertar nada por alguna razón, por lo tanto, la identificación es nula.
¿Hay algún desencadenante configurado en la mesa? Es posible que esté recuperando la identificación de un procedimiento de activación utilizando @@ IDENTITY
Sugeriría usar SCOPE_IDENTITY () o un parámetro de salida para obtener la identificación
Otros consejos
Debe usar SCOPE_IDENTITY ()
en lugar de @@ IDENTITY
en el 99.9% de los casos. Es muy raro que tenga una situación que requiera algo más que SCOPE_IDENTITY()
@@ IDENTITY
devuelve la última IDENTIDAD valor producido en una conexión, independientemente de la tabla que produjo el valor e independientemente del alcance de la declaración que produjo el valor. Si tienes un disparador en un tabla que hace que una identidad sea creado en otra tabla, obtendrá la identidad que se creó por última vez, incluso si fue el desencadenante que lo creó.
SCOPE_IDENTITY ()
devuelve el último valor IDENTITY producido en un conexión y por una declaración en el mismo alcance, independientemente de la tabla eso produjo el valor. SCOPE_IDENTITY (), como @@ IDENTITY, devolverá el último valor de identidad creado en la sesión actual, pero también lo limitará a su actual alcance también.
¿Está seguro de que no hay activadores de auditoría en esa tabla (tal vez agregados por su DBA)?
Varias posibilidades:
-
INSERT no inserta nada (como erikkallen dijo)
-
su declaración (no se muestra) inserta a varias mesas, la última de que no tiene identidad columna
-
el INSERT activa un disparador que se inserta en una mesa sin un columna de identidad - intente SCOPE_IDENTITY () en su lugar
Es posible que desee realizar una verificación para ver si @@ ROWCOUNT > 0.
También hubo problemas conocidos en versiones anteriores de SQL Server con desencadenantes que afectan la capacidad de supervivencia de @@ IDENTITY. ¿Tienes algún desencadenante?
Otra vez cuando esto ocurrió, cambiando
<asp:Parameter Name="newID" Direction="Output" Size="4" />
a
<asp:Parameter Name="newID" Direction="Output" Type="Int32" Size="4" />
solucionó el problema para mí. Al parecer, mi host activó algunos requisitos para una declaración más explícita.
¿Qué es la parte query text ...
? Un INSERTAR, supongo.
¿Podría ser un insert ... select
que no encontró ninguna fila?
Puede recibir valores incorrectos al usar SCOPE_IDENTITY () y @ @IDENTITY . Específicamente cuando la consulta termina ejecutándose como una consulta paralela:
http://support.microsoft.com/default. aspx? scid = kb; es-ES; 2019779