2008-09-05 42 views
72

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.SQL: ¿Cómo obtener el ID de los valores que acabo de INSERTAR?

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

+6

Esto ayudará si se le da algunos detalles de qué base de datos que está utilizando como técnicas varían. – Dhaust

+0

Posible duplicado de [¿La mejor forma de obtener la identidad de la fila insertada?] (Http://stackoverflow.com/questions/42648/best-way-to-get-identity-of-inserted-row) – Michael

Respuesta

54

@@IDENTITY no es ámbito seguro y lo puede poner al el id de otra mesa si tiene un desencadenador de inserción en la tabla original, utilice siempre SCOPE_IDENTITY()

+2

hay errores conocidos con SCOPE_IDENTITY() en sql server 2005, no estoy seguro acerca de 2008, la cláusula OUTPUT puede devolver un conjunto de ID si es necesario –

+1

error conocido con SCOPE_IDENTITY() devolviendo los valores incorrectos: blog.sqlauthority.com/2009/03/24/... the se puede evitar ejecutar el INSERT en un Plan Paralelo de Procesador Múltiple o usar la cláusula OUTPUT –

+4

La URL está cortada en el comentario de @KM. así que espero que este enlace funcione: [SCOPE_IDENTITY Error con el plan paralelo de múltiples procesadores y la solución] (http://blog.sqlauthority.com/2009/03/24/sql-server-2008-scope_identity-bug-with-multi-processor- parallel-plan-and-solution /) –

0
SELECT @@Scope_Identity as Id 

Existe también @@ identidad, pero si usted tiene un disparador, devolverá los resultados de algo que sucedió durante el gatillo, donde SCOPE_IDENTITY respeta su alcance.

2

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

2

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

28

Así es como realizo mis procedimientos de almacenamiento para MSSQL con una identificación autogenerada.

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(); 
14

Si su uso de PHP y MySQL se puede utilizar la función mysql_insert_id() que le dirá el ID de elemento que sólo instered.
Pero sin tu lenguaje y DBMS estoy disparando en la oscuridad aquí.

1

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

10

De nuevo hay un lenguaje respuesta agnóstica, pero en Java que dice 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(); 
} 
+0

Bien, estaba buscando esta – raupach

8

Si está trabajando con Oracle:

insertada en la tabla (campos ....) los valores (los valores ...) el regreso (Lista de campos ...) en (...) las variables

ejemplo:

INSERT INTO PERSONA VALORES (nombre) ('Jack') DEVOLUCIÓN EN ID_PERSON vIdPerson

o si está llamando desde ... Java con una CallableStatement (SRY, que es mi campo)

INSERTAR EN LOS VALORES DE PERSONA (NOMBRE) ('JACK') DEVOLVER ID_PERSON A?

y declarar un parámetro autput por la declaración

4

Una nota importante es que el uso de consultas SQL proveedor para recuperar el último registro insertado ID son seguros de usar sin temor acerca de las conexiones concurrentes.

Siempre pensé que tenía que crear una transacción para INSERTAR una línea y luego SELECCIONAR la última ID insertada para evitar recuperar una ID insertada por otro cliente.

Pero estas consultas específicas del proveedor siempre recuperan la última ID insertada para la conexión actual a la base de datos. Significa que la última ID insertada no puede verse afectada por otras inserciones de cliente siempre que usen su propia conexión de base de datos.

6

No hay una forma estándar de hacerlo (al igual que no existe una forma estándar de crear ID autoincrementables). Aquí hay dos formas de hacerlo en PostgreSQL. Asumir esta es tu tabla:

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

Puede hacerlo en dos estados, siempre y cuando sean declaraciones consecutivos en la misma conexión (esto estará seguro en PHP con la agrupación de conexiones debido a que PHP no da la conexión de nuevo a la piscina hasta la secuencia de comandos se hace):

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

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

La otra forma es utilizar cláusula DEVOLVER de PostgreSQL en la declaración INSERT:

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

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

+0

, esta identificación devuelta dará lugar en el objeto Resultset para Java? –

3

Para SQL 2005:

Suponiendo que la siguiente definición de tabla:

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

Usted puede usar la siguiente:

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

que devolverá el valor de la columna ID.

+0

Esto todavía funciona muy bien en las versiones más nuevas de SQL Server. –

2

Así lo hice con 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(); 
0
  1. insertar la fila con un GUID conocido.
  2. busque el campo autoId con este guid.

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

0

un entorno basado Solución Oracle:

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 
13

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 sentencia INSERT inserta varias filas.

2
sql = "INSERT INTO MyTable (Name) VALUES (@Name);" + 
     "SELECT CAST(scope_identity() AS int)"; 
SqlCommand cmd = new SqlCommand(sql, conn); 
int newId = (int)cmd.ExecuteScalar(); 
4

Desde el sitio me encontré con las siguientes cosas:

SQL SERVER – @@IDENTITY vs SCOPE_IDENTITY() vs IDENT_CURRENT – Retrieve Last Inserted Identity of Record 25 de marzo de 2007 por pinaldave

SELECT @@ IDENTITY Devuelve el último valor de identidad producido en una conexión, sin tener en cuenta de la tabla que produjo el valor, e independientemente del alcance de la declaración que produjo el valor. @@ IDENTITY devolverá el último valor de identidad ingresado en una tabla en su sesión actual. Mientras que @@ IDENTITY está limitado a la sesión actual, no está limitado al alcance actual. Si tiene un desencadenante en una tabla que hace que se cree una identidad en otra tabla, obtendrá la identidad que se creó en último lugar, incluso si fue el desencadenador que lo creó.

SELECT SCOPE_IDENTITY() Devuelve el último valor de IDENTIDAD producido en una conexión y por una declaració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 alcance actual. En otras palabras, devolverá el último valor de identidad que creó explícitamente, en lugar de la identidad creada por un desencadenante o una función definida por el usuario.

SELECCIONAR 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 de la instrucción que produjo el valor. IDENT_CURRENT no está limitado por el alcance 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 cualquier ámbito.

+0

¡Gracias por explicar esto! – doug

2

MS SQL Server: esta es una buena solución, incluso si insertar 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 
0

respuesta más simple:

command.ExecuteScalar() 

por defecto devuelve la primera columna

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

Copiado del MSDN

Cuestiones relacionadas