oracle - ORA-01008: no todas las variables están vinculadas. Ellos están atados
data-binding oracle9i (6)
Encontré cómo ejecutar la consulta sin error, pero dudo en llamarla una "solución" sin realmente entender la causa subyacente.
Esto se parece más al comienzo de mi consulta real:
-- Comment
-- More comment
SELECT rf.flowrow, rf.stage, rf.process,
rf.instr instnum, rf.procedure_id, rtd_history.runtime, rtd_history.waittime
FROM
(
-- Comment at beginning of subquery
-- These two comment lines are the problem
SELECT sub2.flowrow, sub2.stage, sub2.process, sub2.instr, sub2.pid
FROM ( ...
El segundo grupo de comentarios arriba, al comienzo de la subconsulta, era el problema. Cuando se elimina, la consulta se ejecuta. Otros comentarios están bien. No se trata de una nueva línea deshonesta o faltante que hace que se comente la siguiente línea, porque la siguiente línea es un SELECCIONAR. Una selección faltante produciría un error diferente que "no todas las variables vinculadas".
Pregunté por ahí y encontré varias veces a un compañero de trabajo que se encontró con esto, comentarios que causan fallas en las consultas. ¿Alguien sabe cómo esta puede ser la causa? Entiendo que lo primero que haría un DBMS con los comentarios es ver si contienen consejos, y si no, eliminarlos durante el análisis. ¿Cómo puede un comentario ordinario que no contiene caracteres inusuales (solo letras y un punto) causar un error? Extraño.
Me encontré con un problema de Oracle para el que hasta ahora no he podido encontrar la causa. La siguiente consulta funciona en Oracle SQL developer, pero cuando se ejecuta en .NET arroja:
ORA-01008: no todas las variables vinculadas
He intentado:
- Cambiar el tipo de datos de Oracle para lot_priority (Varchar2 o int32).
- Cambiar el tipo de datos .NET para lot_priority (string o int).
- Un nombre de variable de enlace se usa dos veces en la consulta. Esto no es un problema en mis otras consultas que usan la misma variable enlazada en más de una ubicación, pero solo para asegurarme de que intenté hacer de la segunda instancia su propia variable con un nombre diferente: unirlo por separado.
- Varias formas diferentes de vincular las variables (ver código comentado, y otros).
- Mover la llamada bindByName () alrededor.
- Reemplazar cada variable encuadernada con un literal. He tenido dos variables separadas que causan el problema (: lot_pri y: lot_priprc). Hubo algunos cambios menores que no recuerdo entre los dos. El cambio a los literales hizo que la consulta funcionara, pero necesitan trabajar con el enlace.
Consulta y código a continuación. Los nombres de variables han sido cambiados para proteger a los inocentes:
SELECT rf.myrow floworder, rf.stage, rf.prss,
rf.pin instnum, rf.prid, r_history.rt, r_history.wt
FROM
(
SELECT sub2.myrow, sub2.stage, sub2.prss, sub2.pin, sub2.prid
FROM (
SELECT sub.myrow, sub.stage, sub.prss, sub.pin,
sub.prid, MAX(sub.target_rn) OVER (ORDER BY sub.myrow) target_row
,sub.hflag
FROM (
WITH floc AS
(
SELECT flow.prss, flow.seq_num
FROM rpf@mydblink flow
WHERE flow.parent_p = :lapp
AND flow.prss IN (
SELECT r_priprc.prss
FROM r_priprc@mydblink r_priprc
WHERE priprc = :lot_priprc
)
AND rownum = 1
)
SELECT row_number() OVER (ORDER BY pp.seq_num, rpf.seq_num) myrow,
rpf.stage, rpf.prss, rpf.pin,
rpf.itype, hflag,
CASE WHEN rpf.itype = ''SpecialValue''
THEN rpf.instruction
ELSE rpf.parent_p
END prid,
CASE WHEN rpf.prss = floc.prss
AND rpf.seq_num = floc.seq_num
THEN row_number() OVER (ORDER BY pp.seq_num, rpf.seq_num)
END target_rn
FROM floc, rpf@mydblink rpf
LEFT OUTER JOIN r_priprc@mydblink pp
ON (pp.prss = rpf.prss)
WHERE pp.priprc = :lot_priprc
ORDER BY pp.seq_num, rpf.seq_num
) sub
) sub2
WHERE sub2.myrow >= sub2.target_row
AND sub2.hflag = ''true''
) rf
LEFT OUTER JOIN r_history@mydblink r_history
ON (r_history.lt = :lt
AND r_history.pri = :lot_pri
AND r_history.stage = rf.stage
AND r_history.curp = rf.prid
)
ORDER BY myrow
public void runMyQuery(string lot_priprc, string lapp, string lt, int lot_pri) {
Dictionary<int, foo> bar = new Dictionary<int, foo>();
using(var con = new OracleConnection(connStr)) {
con.Open();
using(var cmd = new OracleCommand(sql.rtd_get_flow_for_lot, con)) { // Query stored in sql.resx
try {
cmd.BindByName = true;
cmd.Prepare();
cmd.Parameters.Add(new OracleParameter("lapp", OracleDbType.Varchar2)).Value = lapp;
cmd.Parameters.Add(new OracleParameter("lot_priprc", OracleDbType.Varchar2)).Value = lot_priprc;
cmd.Parameters.Add(new OracleParameter("lt", OracleDbType.Varchar2)).Value = lt;
// Also tried OracleDbType.Varchar2 below, and tried passing lot_pri as an integer
cmd.Parameters.Add(new OracleParameter("lot_pri", OracleDbType.Int32)).Value = lot_pri.ToString();
/*********** Also tried the following, more explicit code rather than the 4 lines above: **
OracleParameter param_lapp
= cmd.Parameters.Add(new OracleParameter("lapp", OracleDbType.Varchar2));
OracleParameter param_priprc
= cmd.Parameters.Add(new OracleParameter("lot_priprc", OracleDbType.Varchar2));
OracleParameter param_lt
= cmd.Parameters.Add(new OracleParameter("lt", OracleDbType.Varchar2));
OracleParameter param_lot_pri
= cmd.Parameters.Add(new OracleParameter("lot_pri", OracleDbType.Varchar2));
param_lapp.Value = lastProcedureStackProcedureId;
param_priprc.Value = lotPrimaryProcedure;
param_lt.Value = lotType;
param_lot_pri.Value = lotPriority.ToString();
//***************************************************************/
var reader = cmd.ExecuteReader();
while(reader.Read()) {
// Get values from table (Never reached)
}
}
catch(OracleException e) {
// ORA-01008: not all variables bound
}
}
}
¿Por qué Oracle afirma que no todas las variables están vinculadas?
Es un error en Managed ODP.net - ''Error 21113901: ADMINISTRADO ODP.NET RAISE ORA-1008 CON EL VAR EN SELECCIONAR CONST + BIND SELECCIONADO'' fijado en el parche 23530387 reemplazado por el parche 24591642
Sé que esta es una vieja pregunta, pero no se ha abordado correctamente, por lo que estoy respondiendo a otras personas que pueden encontrarse con este problema.
Por defecto, ODP.net de Oracle vincula variables por posición y trata cada posición como una nueva variable.
Tratar cada copia como una variable diferente y establecer su valor varias veces es una solución y una molestia, como se menciona en furman87, y podría dar lugar a errores, si está intentando reescribir la consulta y mover las cosas.
La forma correcta es establecer la propiedad BindByName de OracleCommand en verdadero de la siguiente manera:
var cmd = new OracleCommand(cmdtxt, conn);
cmd.BindByName = true;
También podría crear una nueva clase para encapsular OracleCommand estableciendo BindByName en verdadero en la creación de instancias, de modo que no tenga que establecer el valor cada vez. Esto se discute en this publicación
Sobre el problema de comentario de Charles: para empeorar las cosas, deja que
:p1 = ''TRIALDEV''
a través de un Parámetro de Comando, luego ejecuta
select T.table_name as NAME, COALESCE(C.comments, ''==='') as DESCRIPTION
from all_all_tables T
Inner Join all_tab_comments C on T.owner = C.owner and T.table_name = C.table_name
where Upper(T.owner)=:p1
order by T.table_name
558 line(s) affected. Processing time: 00:00:00.6535711
y al cambiar la cadena literal de === a ---
select T.table_name as NAME, COALESCE(C.comments, ''---'') as DESCRIPTION
[...from...same-as-above...]
ORA-01008: not all variables bound
Ambas sentencias se ejecutan correctamente en SQL Developer. El código acortado:
Using con = New OracleConnection(cs)
con.Open()
Using cmd = con.CreateCommand()
cmd.CommandText = cmdText
cmd.Parameters.Add(pn, OracleDbType.NVarchar2, 250).Value = p
Dim tbl = New DataTable
Dim da = New OracleDataAdapter(cmd)
da.Fill(tbl)
Return tbl
End Using
End Using
utilizando Oracle.ManagedDataAccess.dll versión 4.121.2.0 con la configuración predeterminada en VS2015 en la plataforma .Net 4.61.
Entonces, en algún lugar de la cadena de llamadas, puede haber un analizador que busque demasiado agresivamente los comentarios de una línea comenzados por: en el comandoTexto. Pero incluso si esto fuera cierto, el mensaje de error "no todas las variables vinculadas" es al menos engañoso.
Tenía un problema similar en una aplicación heredada, pero de "-" era un parámetro de cadena.
Ex.:
Dim cmd As New OracleCommand("INSERT INTO USER (name, address, photo) VALUES (''User1'', ''--'', :photo)", oracleConnection) Dim fs As IO.FileStream = New IO.FileStream("c:/img.jpg", IO.FileMode.Open) Dim br As New IO.BinaryReader(fs) cmd.Parameters.Add(New OracleParameter("photo", OracleDbType.Blob)).Value = br.ReadBytes(fs.Length) cmd.ExecuteNonQuery() ''here throws ORA-01008
Cambiar el valor del parámetro de dirección ''-'' a ''00'' u otra cosa, funciona.
Tiene dos referencias a la variable de vinculación: lot_priprc, aunque debería exigirle que solo establezca el valor de la variable una vez y lo vincule en ambos lugares, he tenido problemas donde esto no funcionaba y tuve que tratar cada copia como una variable diferente Un dolor, pero funcionó.