stored - oracle store procedure c#
C#Oracle Stored Procedure Parameter Order (3)
Con este
PROCEDURE "ADD_BOOKMARK_GROUP" (
"NAME" IN VARCHAR2,
"BOOKMARK_GROUP_ID" IN NUMBER,
"STAFF_ID" IN VARCHAR2,
"MAX_NO" IN INT,
"NUMFOUND" OUT INT,
"NEW_ID" OUT NUMBER) IS
BEGIN
NEW_ID := -1;
SELECT COUNT(*) INTO NUMFOUND FROM BOOKMARK_GROUP_TABLE WHERE STAFF_ID = STAFF_ID;
IF NUMFOUND < MAX_NO THEN
INSERT INTO BOOKMARK_GROUP_TABLE (NAME, BOOKMARK_GROUP_ID, STAFF_ID) VALUES(NAME, BOOKMARK_GROUP_ID, STAFF_ID);
SELECT BGT_SEQUENCE.currval INTO NEW_ID FROM dual;
END IF;
END;
Me parece interesante que si no agrego parámetros en el orden en que fueron definidos, por ejemplo
OracleCommand cmd = new OracleCommand("ADD_BOOKMARK_GROUP", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new OracleParameter("NAME", name));
...
cmd.Parameters.Add(new OracleParameter("NEW_ID", OracleDbType.Decimal)).Direction = ParameterDirection.Output;
cmd.Parameters.Add(new OracleParameter("NUMFOUND", OracleDbType.Int32)).Direction = ParameterDirection.Output;
en lugar de
OracleCommand cmd = new OracleCommand("ADD_BOOKMARK_GROUP", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new OracleParameter("NAME", name));
...
cmd.Parameters.Add(new OracleParameter("NUMFOUND", OracleDbType.Int32)).Direction = ParameterDirection.Output;
cmd.Parameters.Add(new OracleParameter("NEW_ID", OracleDbType.Decimal)).Direction = ParameterDirection.Output;
Los valores devueltos por
cmd.Parameters["NEW_ID"].Value.ToString()
y
cmd.Parameters["NUMFOUND"].Value.ToString()
intercambiar, aunque ejecutar el procedimiento a través del VS2008 Server Explorer devuelve datos correctos.
¿Por qué es esto?
No es una respuesta a la pregunta, pero puede usar ''insertar ... regresar ... en'' en lugar de seleccionar bgt_sequence.currval desde dual, por ejemplo:
begin
insert into test (id)
values(test_seq.nextval)
returning id into p_id;
end;
Ver http://www.adp-gmbh.ch/ora/sql/insert_into_x_returning_y.html
No soy un buff de Oracle, así que no puedo verificarlo, pero parece que se pasan por posición (en lugar de pasar por su nombre). El equivalente moral a:
EXEC SomeProc ''Foo'', ''Bar''
en lugar de:
EXEC SomeProc @arg1=''Foo'', @arg2=''Bar''
Esto no es muy poco común: durante años (en los días COM), gran parte de mi código tenía que funcionar con un controlador ADODB de paso por posición.
En este caso, el nombre que proporcione solo sirve como clave local para buscar el valor de la colección de colecciones. Puede verificar fácilmente inventando un nombre:
cmd.Parameters.Add(new OracleParameter("BANANA", ...
cmd.Parameters.Add(new OracleParameter("GUITAR", ...
...
cmd.Parameters["BANANA"].Value.ToString()
cmd.Parameters["GUITAR"].Value.ToString()
Si lo anterior se ejecuta sin error, está pasando por posición. Y se pasan por posición ... luego simplemente agréguenlos en el orden correcto ;-p Y nunca agreguen nuevos parámetros, excepto al final ...
Probablemente pueda establecer el parámetro BindByName en el objeto OracleCommand. Esto funciona para consultas SQL directas con parámetros, no lo he probado con procedimientos almacenados, pero sería lógico ...
cmd.BindByName = true;