ORA-01008: toutes les variables ne sont pas liées. Ils sont liés

j'ai rencontré un problème Oracle pour lequel j'ai été incapable de trouver la cause. La requête ci-dessous fonctionne dans Oracle SQL developer, mais lorsqu'elle est exécutée dans .NET elle lance:

ORA-01008: pas toutes les variables liées

j'ai essayé:

  • modifier le type de données Oracle pour lot_priority (Varchar2 ou int32).
  • modifier le type de données .net pour lot_priority (string ou int).
  • une variable de liaison le nom est utilisé deux fois dans la requête. Ce n'est pas un problème dans mon d'autres requêtes qui utilisent la même variable liée à plus d'un lieu, mais juste pour être sûr que j'ai essayé de faire le deuxième cas son propre variable avec un nom différent et le liant séparément.
  • plusieurs façons différentes de lier les variables (voir code commenté; d'autres également).
  • déplacement de l'appel bindByName ().
  • remplacer chaque variable liée par une valeur littérale. J'ai eu deux les variables causent le problème (:lot_pri et :lot_priprc). Il y a eu quelques changements mineurs dont je ne me souviens pas entre les deux. Le passage à des documents écrits a fait fonctionner la requête, mais ils ont besoin de travailler avec reliure.

Requête de code et de le suivre. Les noms de variables ont été changés pour protéger les innocents:

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
        }
    }
}

pourquoi Oracle prétend que toutes les variables ne sont pas liées?

22
demandé sur Charles Burns 2011-09-21 03:36:03

7 réponses

j'ai trouvé comment exécuter la requête sans erreur, mais j'hésite à l'appeler une "solution" sans vraiment comprendre la cause sous-jacente.

ceci ressemble plus au début de ma requête actuelle:

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

la deuxième série de commentaires ci-dessus, au début du sous-questionnaire, était le problème. Une fois supprimé, la requête s'exécute. Les autres commentaires sont bons. Il ne s'agit pas d'un voyou ou d'une nouvelle ligne manquante causant le commentaire de la ligne suivante, parce que la ligne suivante est un SELECT. Une sélection manquante produirait une erreur différente de "pas toutes les variables liées."

j'ai demandé autour et j'ai trouvé un collègue qui a couru dans ceci -- des commentaires causant des échecs de requête -- plusieurs fois. Personne ne sait comment cela peut être la cause? Je crois comprendre que la toute première chose qu'un SGBD ferait avec les commentaires est de voir s'ils contiennent des indices, et si non, de les supprimer pendant l'analyse. Comment un commentaire ordinaire ne contenant pas de caractère inhabituel les caractères (juste des lettres et une période) causent une erreur? Bizarre.

12
répondu Charles Burns 2016-12-09 20:18:54

je sais qu'il s'agit d'une vieille question, mais elle n'a pas été correctement traitée, donc je vais y répondre pour d'autres qui pourraient rencontrer ce problème.

par défaut Oracle ODP.net lie les variables par position, et traite chaque position comme une nouvelle variable.

traiter chaque copie comme une variable différente et définir sa valeur plusieurs fois est une solution de contournement et une douleur, comme furman87 mentionné, et pourrait conduire à des bogues, si vous essayez de réécrire la requête et déplacer des choses autour.

la bonne façon est de définir la propriété BindByName de OracleCommand à true comme suit:

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

Vous pouvez aussi créer une nouvelle classe pour encapsuler OracleCommand en définissant le BindByName à true sur instanciation, donc vous n'avez pas à définir la valeur à chaque fois. Cette question est discutée dans post

8
répondu Vijay Jagdale 2017-05-23 12:01:42

vous avez deux références à la variable de liaison :lot_priprc -- alors qu'elle devrait exige que vous ne définissiez la valeur de la variable qu'une seule fois et que vous la liiez aux deux endroits, j'ai eu des problèmes où cela n'a pas fonctionné et j'ai dû traiter chaque copie comme une variable différente. Une douleur, mais il a travaillé.

7
répondu furman87 2011-09-21 13:17:48

sur le problème de commentaire de Charles: pour aggraver les choses, laissez

:p1 = 'TRIALDEV'

via un paramètre de commande, puis exécutez

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

et en changeant la chaîne littérale de = = = à - - -

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

ORA-01008: not all variables bound

les deux instructions exécutent fine dans le développeur SQL. Le raccourcissement de 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

utiliser Oracle.ManagedDataAccess.dll Version 4.121.2.0 avec les paramètres par défaut dans VS2015 sur la plate-forme.Net 4.61.

Donc quelque part dans la chaîne d'appel, il peut y avoir un analyseur qui est un peu trop agressif à la recherche de commentaires d'une ligne commencée par -- dans le texte de commande. Mais même si cela était vrai, le message d'erreur "pas de toutes les variables liées" est au moins trompeuse.

1
répondu Zartag 2016-01-04 18:35:39

C'est un bug dans Managed ODP.net - fixe dans le patch 23530387 remplacé par le patch 24591642

1
répondu durzy 2017-06-16 11:06:13

est venu ici à la recherche d'aide comme j'ai eu la même erreur en exécutant une instruction listée ci-dessous en passant par un cours D'Udemy:

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

j'avais été capable de lancer des énoncés avec des variables de substitution auparavant. Commentaire de Charles Burns sur la possibilité de serveur atteignant un certain seuil tout en recréant les variables m'a incité à me déconnecter et redémarrer le développeur SQL. La déclaration a couru bien après la connexion.

j'ai Pensé partager pour quiconque de s'aventurer ici avec une question de portée limitée comme la mienne.

1
répondu Qudsia 2018-10-01 02:17:23

j'ai eu un problème similaire dans une application ancienne, mais de " -- " était un paramètre de chaîne.

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

changer la valeur du paramètre adresse ' -- ' en '00' ou autre chose, ça marche.

0
répondu Roger 2016-06-08 16:58:05