webentwicklung-frage-antwort-db.com.de

ORA-01008: Nicht alle Variablen sind gebunden. Sie sind gebunden

Ich bin auf ein Oracle-Problem gestoßen, für das ich bisher die Ursache nicht finden konnte .. Die unten stehende Abfrage funktioniert in Oracle SQL-Entwickler, aber wenn sie in .NET ausgeführt wird, wird Folgendes ausgelöst:

ORA-01008: Nicht alle Variablen sind gebunden

Ich habe es versucht:

  • Ändern des Oracle-Datentyps für lot_priority (Varchar2 oder int32).
  • Ändern des .NET-Datentyps für lot_priority (string oder int).
  • Ein Bindevariablenname wird zweimal in der Abfrage verwendet. Dies ist kein Problem in meinen Anderen Abfragen, die dieselbe gebundene Variable an mehr als einer Position verwenden, aber um sicherzugehen, dass ich versucht habe, die zweite Instanz ihrer .__ es separat binden.
  • Verschiedene Arten der Bindung der Variablen (siehe kommentierter Code; Auch andere).
  • Den bindByName () - Aufruf verschieben.
  • Jede gebundene Variable durch ein Literal ersetzen. Ich hatte zwei getrennte Variablen, die das Problem verursachen (: lot_pri und: lot_priprc). Es gab einige kleinere Änderungen, an die ich mich nicht erinnern kann. Durch das Umstellen auf Literale wurde die Abfrage funktioniert, aber sie müssen mit dem Binden arbeiten.

Abfrage und Code folgen. Variablennamen wurden geändert, um die Unschuldigen zu schützen:

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 [email protected] flow
                WHERE flow.parent_p = :lapp
                AND flow.prss IN (
                    SELECT r_priprc.prss
                    FROM [email protected] 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, [email protected] rpf
            LEFT OUTER JOIN [email protected] 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 [email protected] 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
        }
    }
}

Warum behauptet Oracle, dass nicht alle Variablen gebunden sind?

23
Charles Burns

Ich habe gefunden, wie die Abfrage ohne Fehler ausgeführt werden kann, aber ich zögere, sie "Lösung" zu nennen, ohne die eigentliche Ursache wirklich zu verstehen.

Dies ähnelt eher dem Beginn meiner eigentlichen Abfrage:

-- 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 ( ...

Der zweite Satz von Kommentaren oben am Anfang der Unterabfrage war das Problem. Nach dem Entfernen wird die Abfrage ausgeführt. Andere Kommentare sind in Ordnung .. Dies ist nicht eine Angelegenheit von irgendeinem Schurken oder fehlendem Newline, was dazu führt, dass die folgende Zeile kommentiert wird, da die folgende Zeile ein SELECT ist. Eine fehlende Auswahl würde einen anderen Fehler ergeben als "nicht alle Variablen gebunden".

Ich habe herumgefragt und einen Kollegen gefunden, der sich mit diesem Problem befasst hat - Kommentare, die Abfrageschäden verursachen - mehrmals ... Weiß jemand, wie dies die Ursache sein kann? Ich verstehe, dass ein DBMS als allererstes mit Kommentaren anfängt zu sehen, ob sie Hinweise enthalten, und wenn nicht, entfernen Sie sie während des Parsings. Wie kann ein normaler Kommentar, der keine ungewöhnlichen Zeichen enthält (nur Buchstaben und ein Punkt), einen Fehler verursachen? Bizarr.

13
Charles Burns

Ich weiß, dass dies eine alte Frage ist, aber sie wurde nicht richtig angesprochen, daher beantworte ich sie für andere, die auf dieses Problem stoßen könnten.

Standardmäßig bindet Oracle ODP.net Variablen nach Position und behandelt jede Position als neue Variable. 

Jede Kopie als eine andere Variable zu behandeln und den Wert mehrmals festzulegen, ist eine Problemumgehung und ein Schmerz, wie von furman87 erwähnt wurde. Dies kann zu Fehlern führen, wenn Sie versuchen, die Abfrage neu zu schreiben und Dinge zu verschieben.

Der korrekte Weg ist, die BindByName-Eigenschaft von OracleCommand wie folgt auf true zu setzen:

var cmd = new OracleCommand(cmdtxt, conn);
cmd.BindByName = true;

Sie können auch eine neue Klasse erstellen, um OracleCommand einzukapseln, indem Sie BindByName bei der Instantiierung auf "true" setzen, sodass Sie den Wert nicht jedes Mal festlegen müssen. Dies wird in this post diskutiert

8
Vijay Jagdale

Sie haben zwei Verweise auf die: lot_priprc-Bindungsvariable. Während sollte Sie nur einmal den Wert der Variablen festlegen und an beiden Stellen binden müssen, hatte ich Probleme, wo dies nicht funktionierte und behandelt werden musste jede Kopie als andere Variable. Ein Schmerz, aber es hat funktioniert.

7
furman87

Kam hier auf der Suche nach Hilfe, da beim Ausführen eines Udemy-Kurses derselbe Fehler beim Ausführen einer nachstehenden Anweisung aufgetreten ist: 

INSERT INTO departments (department_id, department_name)
                  values( &dpet_id, '&dname');  

Ich konnte vorher Anweisungen mit Substitutionsvariablen ausführen. In einem Kommentar von Charles Burns über die Möglichkeit, dass der Server während der Neuerstellung der Variablen einen bestimmten Schwellenwert erreichte, wurde ich aufgefordert, mich abzumelden und den SQL Developer neu zu starten. Nachdem Sie sich wieder angemeldet hatten, lief die Anweisung einwandfrei.

Ich hätte gedacht, ich würde es für alle anderen teilen, die sich hier mit einem begrenzten Umfang als meinig aufhalten.

1
Qudsia

Die Lösung in meiner Situation war eine ähnliche Antwort auf Charles Burns; und das Problem war auf SQL-Code-Kommentare zurückzuführen. 

Ich habe einen bereits funktionierenden SSRS-Bericht mit Oracle-Datenquelle erstellt (oder aktualisiert). Ich habe dem Bericht einige weitere Parameter hinzugefügt, ihn in Visual Studio getestet, er funktioniert hervorragend, also stellte ich ihn auf dem Berichtsserver bereit. Wenn der Bericht ausgeführt wird, hat der Bericht auf dem Server die folgende Fehlermeldung erhalten:

"ORA-01008: nicht alle Variablen gebunden"

Ich habe viele verschiedene Dinge ausprobiert (TNSNames.ora-Datei, die auf dem Server installiert ist, Einzelzeilenkommentare entfernt, Dataset-Abfragezuordnung überprüfen). Es kam darauf an, dass ich Kommentarblock direkt danach entfernen den WHERE keyword. Die Fehlermeldung wurde nach Verschieben des Kommentarblocks nach dem WHERE CLAUSE conditions behoben. Ich habe auch andere Kommentare im Code. Es war nur eine nach dem WHERE-Schlüsselwort, das den Fehler verursachte. 

SQL mit Fehler: "ORA-01008: nicht alle Variablen gebunden" ...

WHERE
/*
    OHH.SHIP_DATE BETWEEN TO_DATE('10/1/2018', 'MM/DD/YYYY') AND TO_DATE('10/31/2018', 'MM/DD/YYYY')
    AND OHH.STATUS_CODE<>'DL'
    AND OHH.BILL_COMP_CODE=100
    AND OHH.MASTER_ORDER_NBR IS NULL
*/

    OHH.SHIP_DATE BETWEEN :paramStartDate AND :paramEndDate
    AND OHH.STATUS_CODE<>'DL'
    AND OHH.BILL_COMP_CODE IN (:paramCompany)
    AND LOAD.DEPART_FROM_WHSE_CODE IN (:paramWarehouse) 
    AND OHH.MASTER_ORDER_NBR IS NULL
    AND LOAD.CLASS_CODE IN (:paramClassCode) 
    AND CUST.CUST_CODE || '-' || CUST.CUST_SHIPTO_CODE IN (:paramShipto) 

SQL wird erfolgreich auf dem Berichtsserver ausgeführt ...

WHERE
    OHH.SHIP_DATE BETWEEN :paramStartDate AND :paramEndDate
    AND OHH.STATUS_CODE<>'DL'
    AND OHH.BILL_COMP_CODE IN (:paramCompany)
    AND LOAD.DEPART_FROM_WHSE_CODE IN (:paramWarehouse) 
    AND OHH.MASTER_ORDER_NBR IS NULL
    AND LOAD.CLASS_CODE IN (:paramClassCode) 
    AND CUST.CUST_CODE || '-' || CUST.CUST_SHIPTO_CODE IN (:paramShipto)   
/*
    OHH.SHIP_DATE BETWEEN TO_DATE('10/1/2018', 'MM/DD/YYYY') AND TO_DATE('10/31/2018', 'MM/DD/YYYY')
    AND OHH.STATUS_CODE<>'DL'
    AND OHH.BILL_COMP_CODE=100
    AND OHH.MASTER_ORDER_NBR IS NULL
*/

Der Bildschirm für die Zuordnung der Dataset-Parameter sieht folgendermaßen aus: 

 enter image description here

Es ist ein Fehler in Managed ODP.net - 'Fehler 21113901: MANAGED ODP.NET RAISE ORA-1008 VERWENDEN EINZELZETTELKONST + BIND VAR IN SELECT' behoben im Patch 23530387 durch Patch 24591642 ersetzt

1
durzy

Zu Charles 'Kommentarproblem: Um die Dinge noch schlimmer zu machen, lassen Sie

:p1 = 'TRIALDEV'

über einen Befehlsparameter ausführen und dann ausführen

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

und beim Ändern der Literalzeichenfolge von === in ---

select T.table_name as NAME, COALESCE(C.comments, '---') as DESCRIPTION
[...from...same-as-above...]

ORA-01008: not all variables bound

Beide Anweisungen werden in SQL Developer einwandfrei ausgeführt. Der gekürzte Code:

            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

verwenden von Oracle.ManagedDataAccess.dll Version 4.121.2.0 mit den Standardeinstellungen in VS2015 auf der Plattform .Net 4.61.

Irgendwo in der Aufrufkette könnte es also einen Parser geben, der etwas zu aggressiv nach einzeiligen Kommentaren sucht, die von - im Befehlstext gestartet werden. Aber auch wenn dies wahr wäre, ist die Fehlermeldung "Nicht alle Variablen gebunden" zumindest irreführend.

1
Zartag

Ich hätte ein ähnliches Problem in einer älteren Anwendung, aber de "-" war ein String-Parameter.

Ex.:

 Dim cmd As New OracleCommand ("INSERT IN USER (Name, Adresse, Foto)) VALUES ('User1', '-',: photo)", oracleConnection) 
 Dim fs As IO.FileStream = New IO .FileStream ("c:\img.jpg", IO.FileMode.Open) 
 Dim als New IO.BinaryReader (fs) 
 Cmd.Parameters.Add (Neuer OracleParameter ("photo", OracleDbType.Blob )). Value = br.ReadBytes (fs.Length) 
 Cmd.ExecuteNonQuery () 'löst hier ORA-01008 .__ aus.

Das Ändern des Adressparameterwerts '-' in '00' oder eine andere Sache funktioniert.

0
Roger