2009-08-26 19 views
12

Sé que en Oracle Puedo obtener el id. Generado (o cualquier otra columna) de una fila insertada como parámetro de salida. Ex:¿Cómo obtener el ID generado desde una fila insertada usando ExecuteScalar?

insert into foo values('foo','bar') returning id into :myOutputParameter 

¿Hay una manera de hacer lo mismo, pero utilizando en lugar de ExecuteScalar ExecuteNonQuery?

No quiero usar parámetros de salida o procedimientos almacenados.

ps: estoy usando Oracle, no servidor sql !!!

+0

Poner esto como un comentario, ya que es especulativa, pero ha SQL Server "@@ SCOPE_IDENTITY" por lo que la declaración puede ser "insertar en fo ....; select @@ SCOPE_IDENTITY" ... ¿Tiene Oracle tiene algo ¿similar? – Rob

+2

esa sería la respuesta :) – andrecarlucci

+0

En cuanto a SQL Server, no sé acerca de esta variable del sistema @@ SCOPE_IDENTITY, por lo tanto sé sobre una función escalar IDENT_CURRENT que hace lo mismo (SELECT IDENT_CURRENT (N'TableName ') –

Respuesta

6

Oracle utiliza secuencias en cuanto a sus columnas de identidad, si se puede decir así.

Si ha establecido una secuencia para la clave principal de su tabla, también debe escribir un desencadenador que insertará Sequence.NextValue en el campo de clave principal.

Suponiendo que ya está familiarizado con este concepto, simplemente consulte su secuencia, luego obtendrá su respuesta. Lo que se practica mucho en Oracle es hacerse una función que devolverá una INT, luego dentro de su función, realizará su INSERCIÓN. Suponiendo que haya configurado su disparador correctamente, podrá devolver el valor de su secuencia al consultarlo.

He aquí un ejemplo:

CREATE TABLE my_table (
    id_my_table INT PRIMARY KEY 
    description VARCHAR2(100) NOT NULL 
) 

CREATE SEQUENCE my_table_seq 
    MINVALUE 1 
    MAXVALUE 1000 
    START WITH 1 
    INCREMENT BY 2 
    CACHE 5; 

Si desea administrar el incremento automático a sí mismo, se hace así:

INSERT INTO my_table (
    id_my_table, 
    description 
) VALUES (my_table_seq.NEXTVAL, "Some description"); 
COMMIT; 

Por otro lado, si usted desea no se preocupan por el PRIMARIA Incremento de KEY, puede proceder con un disparador.

CREATE OR REPLACE TRIGGER my_table_insert_trg 
    BEFORE INSERT ON my_table FOR EACH ROW 
BEGIN 
    SELECT my_table_seq.NEXTVAL INTO :NEW.id_my_table FROM DUAL; 
END; 

Entonces, cuando se está insertando, sólo hay que escribir la instrucción INSERT de la siguiente manera:

INSERT INTO my_table (description) VALUES ("Some other description"); 
COMMIT; 

después de una inserción, supongo que querrá

SELECT my_table_seq.CURRVAL 

o algo como esto para seleccionar el valor real de su secuencia.

Éstos son algunos enlaces para ayudar:

http://www.orafaq.com/wiki/Sequence

http://www.orafaq.com/wiki/AutoNumber_and_Identity_columns

Espero que esto ayude!

+0

Hola Will, Bueno, no pensé en seq.CURRVAL. Pero, ¿esto es salvar? Quiero decir, si alguien inserta una fila entre mis dos llamadas (insertar, seleccionar)? – andrecarlucci

+0

Normalmente, este tipo de operaciones son relativas a la conexión/sesión de su base de datos para evitar que ocurra. No puedo encontrarlo en blanco y negro para Oracle, pero esa es la forma en que funciona para MySQL, Access, SQL Server, etc. –

+1

Oracle realizará las inserciones de forma secuencial. Una vez que pasó por la primera instrucción INSERT y devolvió el nuevo valor de la secuencia actual, realizará la otra inserción. Según lo declarado por el Sr. Crazy Joe Malloy, esa no es la forma de hacerlo de todos modos. :) No debemos olvidar que Oracle funciona de forma transaccional. Por lo tanto, no se seleccionará NEXTVALUE de la secuencia, siempre que la instrucción INSERT no esté COMPROMETIDA. En cualquier caso, si mal no recuerdo, hay algún tipo de bloqueo en alguna parte (TABLA o SECUENCIA) mientras se realiza la transacción. –

24

Si está en Oracle, debe usar ExecuteNonQuery y ResultParameter. No hay forma de escribir esto como consulta.

using (OracleCommand cmd = con.CreateCommand()) { 
    cmd.CommandText = "insert into foo values('foo','bar') returning id into :myOutputParameter"; 
    cmd.Parameters.Add(new OracleParameter("myOutputParameter", OracleDbType.Decimal), ParameterDirection.ReturnValue); 
    cmd.ExecuteNonQuery(); // an INSERT is always a Non Query 
    return Convert.ToDecimal(cmd.Parameters["myOutputParameter"].Value); 
} 
+0

What es la diferencia entre 'ParameterDirection.ReturnValue' y' ParameterDirection.Output'? – Timeless

+0

ParameterDirection.ReturnValue es el resultado de una función. ParameterDirection.Output es para parámetros en métodos (funciones o procedimientos) que se definen como out o inout. – Christian13467

+1

Suspiro ! Sigo recibiendo 'ORA-12537: sesión de red: fin de archivo' en ExecuteNonQuery sin importar lo que intento :( –

1

una posible forma si se puede agregar una columna llamada "guid" a la tabla: al insertar un registro desde C#, generar un guid y escribirlo en la columna guid. luego realice un selecto con el GUID generado, y usted tiene el id del registro insertado :)

0
Select t.userid_pk From Crm_User_Info T 
Where T.Rowid = (select max(t.rowid) from crm_user_info t) 

esto devolverá su identificación requerida

2

Puede utilizar a continuación código.

using (OracleCommand cmd = conn.CreateCommand()) 
    { 
     cmd.CommandText = @"INSERT INTO my_table(name, address) 
      VALUES ('Girish','Gurgaon India') 
      RETURNING my_id INTO :my_id_param"; 
     OracleParameter outputParameter = new OracleParameter("my_id_param", OracleDbType.Decimal); 
     outputParameter.Direction = ParameterDirection.Output; 
     cmd.Parameters.Add(outputParameter);   
     cmd.ExecuteNonQuery();   
     return Convert.ToDecimal(outputParameter.Value); 
    } 
Cuestiones relacionadas