ultimo registro obtener insertado sql database ms-access primary-key jet

obtener el ultimo registro insertado sql



@@ IDENTITY después de la instrucción INSERT siempre devuelve 0 (13)

¿Hay algún desencadenante en su mesa que pueda estar insertándose en otras tablas? En general, se nos aconseja no utilizar @@ Identity a favor de IDENT_CURRENT para que pueda garantizar que la identidad devuelta corresponde a la tabla que acaba de insertar.

Necesito una función que ejecute una instrucción INSERT en una base de datos y devuelva la clave primaria Auto_Increment. Tengo el siguiente código C # pero, aunque la instrucción INSERT funciona bien (puedo ver el registro en la base de datos, la PK se genera correctamente y filas == 1), el valor de identificación es siempre 0. Cualquier idea sobre lo que podría estar pasando ¿incorrecto?

public int ExecuteInsertStatement(string statement) { InitializeAndOpenConnection(); int id = -1; IDbCommand cmdInsert = connection.CreateCommand(); cmdInsert.CommandText = statement; int rows = cmdInsert.ExecuteNonQuery(); if (rows == 1) { IDbCommand cmdId = connection.CreateCommand(); cmdId.CommandText = "SELECT @@Identity;"; id = (int)cmdId.ExecuteScalar(); } return id; } private void InitializeAndOpenConnection() { if (connection == null) connection = OleDbProviderFactory.Instance.CreateConnection(connectString); if(connection.State != ConnectionState.Open) connection.Open(); }

En respuesta a las respuestas, intenté:

public int ExecuteInsertStatement(string statement, string tableName) { InitializeAndOpenConnection(); int id = -1; IDbCommand cmdInsert = connection.CreateCommand(); cmdInsert.CommandText = statement + ";SELECT OID FROM " + tableName + " WHERE OID = SCOPE_IDENTITY();"; id = (int)cmdInsert.ExecuteScalar(); return id; }

pero ahora obtengo el error "Caracteres encontrados después del final de la declaración de SQL"

Estoy usando una base de datos MS Access con conexión OleDb, Provider = Microsoft.Jet.OLEDB.4.0


¿No están la mayoría de los que responden olvidando que el asker no está usando SQL Server?

Aparentemente, MS Access 2000 y posteriores no son compatibles con @@ IDENTITY . La alternativa es "Usando el evento RowUpdated, puede determinar si se ha producido un INSERT, recuperar el último valor @@ IDENTITY y colocarlo en la columna de identidad de la tabla local en el DataSet".

Y sí, esto es para VBA incorporado en Access DB. Eso todavía se puede llamar fuera de Access a través de la Biblioteca de objetos de acceso.

Editar: bien, es compatible, lo siento por la aturdida respuesta de la mañana. Pero el resto de esta respuesta podría ayudar.


1) combine la instrucción INSERT y SELECT (concatene con ";") en el comando 1 db

2) use SCOPE_IDENTITY () en lugar de @@ IDENTITY

INSERT INTO blabla ...; SELECCIONAR OID FROM tabla WHERE OID = SCOPE_IDENTITY ()

- actualización:

como resultó que la pregunta estaba relacionada con MS ACCESS, encontré este artículo que sugiere que simplemente reutilizar el primer comando y establecer su CommandText en "SELECT @@ IDENTITY" debería ser suficiente.


Creo que @@ identity solo es válido en el alcance del comando, en su caso cuando ejecuta "statement".

Modifique su "declaración" para que el procedimiento almacenado devuelva el valor de @@ IDENTITY justo después de la instrucción INSERT, y léala como el código de retorno de la ejecución del procedimiento almacenado.


Creo que debe tener la identidad Select @@ con el primer comando de creación; intente anexarlo mediante "; SELECT @@ Identity" y .ExecuteScalar la instrucción de inserción


El proveedor Microsoft.Jet.OLEDB.4.0 es compatible con los motores de base de datos Jet v3 y Jet v4; sin embargo, SELECT @@ IDENTITY no es compatible con Jet v3.

MSAccess 97 es Jet v3 y no admite SELECT @@ IDENTITY; Es compatible con MSAccess 2000 y superior.


Está utilizando Jet (no SQL Server) y Jet solo puede manejar una instrucción SQL por comando, por lo tanto, necesita ejecutar SELECT @@IDENTITY en un comando separado, obviamente asegurando que usa la misma conexión que INSERT .


La respuesta corta:
1. Crea dos comandos, cada uno aceptando una sola consulta.
2. La primera consulta sql es el registro INSERT.
3. La segunda consulta sql es "SELECT @@ Identity;" que devuelve el Autonumérico.
4. Use cmd.ExecuteScalar () que devuelve una primera columna de la primera fila.
5. El resultado del resultado devuelto es el valor de Autonumérico generado en la consulta de inserción actual.

Se hace referencia desde este enlace . El código de ejemplo es como debajo. Tenga en cuenta la diferencia para "MISMA conexión VS NUEVA conexión". La MISMA conexión da la salida deseada.

class Program { static string path = @"<your path>"; static string db = @"Test.mdb"; static void Main(string[] args) { string cs = String.Format(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}/{1}", path, db); // Using the same connection for the insert and the SELECT @@IDENTITY using (OleDbConnection con = new OleDbConnection(cs)) { con.Open(); OleDbCommand cmd = con.CreateCommand(); for (int i = 0; i < 3; i++) { cmd.CommandText = "INSERT INTO TestTable(OurTxt) VALUES (''" + i.ToString() + "'')"; cmd.ExecuteNonQuery(); cmd.CommandText = "SELECT @@IDENTITY"; Console.WriteLine("AutoNumber: {0}", (int)cmd.ExecuteScalar()); } con.Close(); } // Using a new connection and then SELECT @@IDENTITY using (OleDbConnection con = new OleDbConnection(cs)) { con.Open(); OleDbCommand cmd = con.CreateCommand(); cmd.CommandText = "SELECT @@IDENTITY"; Console.WriteLine("/nNew connection, AutoNumber: {0}", (int)cmd.ExecuteScalar()); con.Close(); } } }

Esto debería producir el resultado autoexplicativo:

AutoNumber: 1 <br> AutoNumber: 2 <br> AutoNumber: 3 <br> New connection, AutoNumber: 0


Mientras usa Access, eche un vistazo a este artículo de aspfaq, baje hasta aproximadamente la mitad de la página. El código está en ASP clásico, pero ojalá los principios aún se mantengan.

El SELECT @@ Identity termina siendo tratado como un contexto de ejecución separado, creo. El código que debería funcionar sería:

public int ExecuteInsertStatement(string statement) { InitializeAndOpenConnection(); IDbCommand cmdInsert = connection.CreateCommand(); cmdInsert.CommandText = statement + "; SELECT @@Identity"; object result = cmdInsert.ExecuteScalar(); if (object == DBNull.Value) { return -1; } else { return Convert.ToInt32(result); } }

Sin embargo, probablemente desee / necesite ordenar la concatenación que agrega el ''SELECCIONAR @@ Identidad'' al final del código.


Si desea recuperar el valor del número de ejecución automática de la transacción que está insertando y su entorno siguiente, 1. La base de datos es MsAccess. 2. El controlador es Jet4 con una cadena de conexión como esta "Provider = Microsoft.Jet.OLEDB.4.0; Password = {0}; Data Source = {1}; Persist Security Info = True" 3. use Oledb

Puedes aplicar mi ejemplo a tu código

OleDbConnection connection = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Password={0};Data Source={1};Persist Security Info=True",dbinfo.Password,dbinfo.MsAccessDBFile); connection.Open(); OleDbTransaction transaction = null; try{ connection.BeginTransaction(); String commandInsert = "INSERT INTO TB_SAMPLE ([NAME]) VALUES (''MR. DUKE'')"; OleDbCommand cmd = new OleDbCommand(commandInsert , connection, transaction); cmd.ExecuteNonQuery(); String commandIndentity = "SELECT @@IDENTITY"; cmd = new OleDbCommandcommandIndentity, connection, transaction); Console.WriteLine("New Running No = {0}", (int)cmd.ExecuteScalar()); connection.Commit(); }catch(Exception ex){ connection.Rollback(); }finally{ connection.Close(); }


Verifique la configuración de su base de datos. Hace un tiempo tuve un problema similar y descubrí que la configuración de conexión de SQL Server ''no count'' estaba habilitada.

En SQL Server Management Studio, puede encontrarlo haciendo clic con el botón derecho en el servidor en el Explorador de objetos, seleccione Propiedades y luego vaya a la página Conexiones. Mire la configuración de "Opciones de conexión predeterminadas"


debe devolver la identidad al mismo tiempo que abre la conexión inicial. Devuelve un conjunto de resultados de tu inserción o una variable de salida.

También debe usar siempre SCOPE_IDENTITY () not @@ identity. Referencia aquí

Deberías agregar

SELECT SCOPE_IDENTITY()

Después de la inserción.


CREATE procedure dbo.sp_whlogin ( @id nvarchar(20), @ps nvarchar(20), @curdate datetime, @expdate datetime ) AS BEGIN DECLARE @role nvarchar(20) DECLARE @menu varchar(255) DECLARE @loginid int SELECT @role = RoleID FROM dbo.TblUsers WHERE UserID = @id AND UserPass = @ps if @role is not null BEGIN INSERT INTO TblLoginLog (UserID, LoginAt, ExpireAt, IsLogin) VALUES (@id, @curdate, @expdate, 1); SELECT @loginid = @@IDENTITY; SELECT @loginid as loginid, RoleName as role, RoleMenu as menu FROM TblUserRoles WHERE RoleName = @role END else BEGIN SELECT '''' as role, '''' as menu END END GO