SQL: ¿Cómo obtener el id de los valores que acabo de insertar?


He insertado algunos valores en una tabla. Hay una columna cuyo valor se genera automáticamente. En la siguiente declaración de mi código, quiero recuperar este valor.

¿Puedes decirme cómo hacerlo de la manera correcta?

 72
Author: a_horse_with_no_name, 2008-09-05

21 answers

@@IDENTITY no es seguro para el alcance y le devolverá el id de otra tabla si tiene un disparador de inserción en la tabla original, siempre use SCOPE_IDENTITY()

 54
Author: SQLMenace,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-04 11:59:07

Así es como hago mis procedimientos de almacén para MSSQL con un ID autogenerado.

CREATE PROCEDURE [dbo].[InsertProducts]
    @id             INT             = NULL OUT,
    @name           VARCHAR(150)    = NULL,
    @desc           VARCHAR(250)    = NULL

AS

    INSERT INTO dbo.Products
       (Name,
        Description)
    VALUES
       (@name,
        @desc)

    SET @id = SCOPE_IDENTITY();
 28
Author: David Basarab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-05 12:31:43

Si está usando PHP y MySQL, puede usar la función mysql_insert_id() que le indicará el ID del elemento que acaba de indicar.
Pero sin tu lenguaje y DBMS estoy filmando en la oscuridad.

 14
Author: UnkwnTech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-05 12:31:47

Esto funciona muy bien en SQL 2005:

DECLARE @inserted_ids TABLE ([id] INT);

INSERT INTO [dbo].[some_table] ([col1],[col2],[col3],[col4],[col5],[col6])
OUTPUT INSERTED.[id] INTO @inserted_ids
VALUES (@col1,@col2,@col3,@col4,@col5,@col6)

Tiene la ventaja de devolver todos los ID si su instrucción INSERT inserta varias filas.

 14
Author: Daniel Schaffer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-23 20:25:55

De nuevo no hay respuesta agnóstica del lenguaje, pero en Java es así:

Connection conn = Database.getCurrent().getConnection();  
PreparedStatement ps =  conn.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);
try {  
    ps.executeUpdate();  
    ResultSet rs = ps.getGeneratedKeys();  
    rs.next();  
    long primaryKey = rs.getLong(1);  
} finally {  
    ps.close();  
}  
 10
Author: Slartibartfast,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-17 16:20:23

Si está trabajando con Oracle:

Insertar en la tabla (Campos....) valores (Valores...) VOLVIENDO (Lista de campos...) EN (variables...)

Ejemplo:

INSERTAR EN PERSONA (NOMBRE) VALORES ('JACK') DEVOLVIENDO ID_PERSON EN vIdPerson

O si está llamando desde... Java con un CallableStatement (sry, es mi campo)

INSERTAR EN PERSONA (NOMBRE) VALORES ('JACK') DEVOLVIENDO ID_PERSON EN ?

Y declarando un parámetro autput para la instrucción

 8
Author: Telcontar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-05 13:05:29

No hay una forma estándar de hacerlo (al igual que no hay una forma estándar de crear identificadores de incremento automático). Aquí hay dos maneras de hacerlo en PostgreSQL. Supongamos que esta es su tabla:

CREATE TABLE mytable (
  id SERIAL PRIMARY KEY,
  lastname VARCHAR NOT NULL,
  firstname VARCHAR
);

Puede hacerlo en dos sentencias siempre y cuando sean sentencias consecutivas en la misma conexión (esto será seguro en PHP con connection pooling porque PHP no devuelve la conexión al pool hasta que su script haya terminado):

INSERT INTO mytable (lastname, firstname) VALUES ('Washington', 'George');
SELECT lastval();

lastval() le da la última valor de secuencia generado automáticamente utilizado en la conexión actual.

La otra forma es usar la cláusula RETURNING de PostgreSQL en el INSERTAR declaración:

INSERT INTO mytable (lastname) VALUES ('Cher') RETURNING id;

Este formulario devuelve un conjunto de resultados al igual que una instrucción SELECT, y también es útil para devolver cualquier tipo de valor predeterminado calculado.

 6
Author: Neall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-05 13:16:30

Una nota importante es que el uso de consultas SQL de proveedor para recuperar el último ID insertado es seguro de usar sin temor a conexiones simultáneas.

Siempre pensé que había que crear una transacción para INSERTAR una línea y luego SELECCIONAR el último ID insertado para evitar recuperar un ID insertado por otro cliente.

Pero estas consultas específicas del proveedor siempre recuperan el último ID insertado para la conexión actual a la base de datos. Significa que el el último ID insertado no puede verse afectado por otras inserciones de clientes siempre que utilicen su propia conexión de base de datos.

 4
Author: Vincent Robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-05 13:11:02

Del sitio me enteré de las siguientes cosas:

SQL SERVER - @ @ IDENTITY vs SCOPE_IDENTITY () vs IDENT_CURRENT-Recuperar la última Identidad insertada del Registro 25 de marzo de 2007 por pinaldave

SELECCIONE @ @ IDENTIDAD Devuelve el último valor de IDENTIDAD producido en una conexión, independientemente de la tabla que produjo el valor e independientemente del alcance de la instrucción que produjo el valor. @@IDENTITY devolverá el último valor de identidad introducido en una tabla en su sesión actual. Mientras @@IDENTITY se limita a la sesión actual, no se limita al ámbito actual. Si tiene un desencadenador en una tabla que hace que se cree una identidad en otra tabla, obtendrá la identidad que se creó por última vez, incluso si fue el desencadenador el que la creó.

SELECCIONE SCOPE_IDENTITY() Devuelve el último valor de IDENTIDAD producido en una conexión y por una instrucción en el mismo ámbito, independientemente de la tabla que 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 ámbito actual. En otras palabras, devolverá el último valor de identidad que haya creado explícitamente, en lugar de cualquier identidad creada por un disparador o una función definida por el usuario.

SELECCIONE IDENT_CURRENT ('tablename') Devuelve el último valor de IDENTIDAD producido en una tabla, independientemente de la conexión que creó el valor e independientemente del alcance del declaración que produjo el valor. IDENT_CURRENT no está limitado por el ámbito y la sesión; está limitado a una tabla especificada. IDENT_CURRENT devuelve el valor de identidad generado para una tabla específica en cualquier sesión y ámbito.

 4
Author: DBinukumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-24 21:55:13

Para SQL 2005:

Asumiendo la siguiente definición de tabla:

CREATE TABLE [dbo].[Test](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [somevalue] [nchar](10) NULL,
) 

Puedes usar lo siguiente:

INSERT INTO Test(somevalue)
OUTPUT INSERTED.ID
VALUES('asdfasdf')

Que devolverá el valor de la columna ID.

 3
Author: NotMe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-05 13:30:56

Recuerde que @@IDENTITY devuelve la identidad creada más recientemente para su conexión actual, no necesariamente la identidad para la fila recientemente agregada en una tabla. Siempre debe usar SCOPE_IDENTITY () para devolver la identidad de la fila recientemente agregada.

 2
Author: Espo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-05 12:29:42

¿Qué base de datos está utilizando? Por lo que sé, no hay un método agnóstico de base de datos para hacer esto.

 2
Author: Matthew Watson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-05 12:29:56

Así es como lo he hecho usando comandos parametrizados.

MSSQL

 INSERT INTO MyTable (Field1, Field2) VALUES (@Value1, @Value2); 
 SELECT SCOPE_IDENTITY(); 

MySQL

 INSERT INTO MyTable (Field1, Field2) VALUES (?Value1, ?Value2);
 SELECT LAST_INSERT_ID();
 2
Author: Wyck Hebert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-05 14:40:50
sql = "INSERT INTO MyTable (Name) VALUES (@Name);" +
      "SELECT CAST(scope_identity() AS int)";
SqlCommand cmd = new SqlCommand(sql, conn);
int newId = (int)cmd.ExecuteScalar();
 2
Author: James Lawruk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-01 15:35:01

Ms SQL Server: esta es una buena solución incluso si inserta más filas:

 Declare @tblInsertedId table (Id int not null)

 INSERT INTO Test ([Title], [Text])
 OUTPUT inserted.Id INTO @tblInsertedId (Id)
 SELECT [Title], [Text] FROM AnotherTable

 select Id from @tblInsertedId 
 2
Author: Jan Remunda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-17 06:39:44

La respuesta de Rob sería la más independiente del proveedor, pero si estás usando MySQL la opción más segura y correcta sería la función incorporada LAST_INSERT_ID().

 1
Author: Tobias Baaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-05 12:37:56
SELECT @@Scope_Identity as Id

También hay @@identity, pero si tiene un trigger, devolverá los resultados de algo que sucedió durante el trigger, donde scope_identity respeta su ámbito.

 0
Author: DevelopingChris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-05 12:29:23
  1. inserte la fila con un guid conocido.
  2. obtenga el campo AutoID con este guid.

Esto debería funcionar con cualquier tipo de base de datos.

 0
Author: dummy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-15 22:12:05

Una Solución Oracle Basada en el Entorno:

CREATE OR REPLACE PACKAGE LAST
AS
ID NUMBER;
FUNCTION IDENT RETURN NUMBER;
END;
/

CREATE OR REPLACE PACKAGE BODY LAST
AS
FUNCTION IDENT RETURN NUMBER IS
    BEGIN
    RETURN ID;
    END;
END;
/


CREATE TABLE Test (
       TestID            INTEGER ,
    Field1      int,
    Field2      int
)


CREATE SEQUENCE Test_seq
/
CREATE OR REPLACE TRIGGER Test_itrig
BEFORE INSERT ON Test
FOR EACH ROW
DECLARE
seq_val number;
BEGIN
IF :new.TestID IS NULL THEN
    SELECT Test_seq.nextval INTO seq_val FROM DUAL;
    :new.TestID := seq_val;
    Last.ID := seq_val;
END IF;
END;
/

To get next identity value:
SELECT LAST.IDENT FROM DUAL
 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-23 20:22:42

En TransactSQL, puede usar la cláusula OUTPUT para lograr eso.

INSERT INTO my_table(col1,col2,col3) OUTPUT INSERTED.id VALUES('col1Value','col2Value','col3Value')

VIE: http://msdn.microsoft.com/en-us/library/ms177564.aspx

 0
Author: SuperLucky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-08 06:40:45

La respuesta más simple:

command.ExecuteScalar()

Por defecto devuelve la primera columna

Valor devuelto Tipo: System.Objeto La primera columna de la primera fila del conjunto de resultados, o una referencia nula (Nada en Visual Basic) si el conjunto de resultados está vacío. Devuelve un máximo de 2033 caracteres.

Copiado de MSDN

 0
Author: LiranBo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-28 20:57:40