Question

Je dois utiliser l'exécution SQL dynamique sur Oracle où je ne connais pas le nombre exact de variables de liaison utilisées dans le code SQL avant l'exécution.

Existe-t-il un moyen d'utiliser un nombre variable de variables de liaison dans l'appel à EXECUTE IMMEDIATE ?

Plus précisément, je dois passer un paramètre dans le code SQL inconnu, mais je ne sais pas à quelle fréquence il sera utilisé à cet emplacement.

j'ai essayé quelque chose comme

EXECUTE IMMEDIATE 'SELECT SYSDATE FROM DUAL WHERE :var = :var' USING 1;

Mais il a rejeté avec ORA-01008: toutes les variables ne sont pas liées.

Était-ce utile?

La solution

Vous ne pouvez pas faire cela avec EXECUTE IMMEDIATE . Cependant, vous pouvez le faire en utilisant le package DBMS_SQL d'Oracle. Le Le Guide du développeur d'applications de base de données a une comparaison entre les méthodes EXECUTE IMMEDIATE que vous connaissez et dbms_sql . Cette page documente DBMS_SQL , mais contient quelques exemples (liés ci-dessus) qui devraient vous aider à démarrer (l'exemple 1 est un simple cas d'exécution d'une instruction pouvant comporter un nombre arbitraire de variables de liaison). DBMS_SQL est beaucoup plus lourd du point de vue du code, mais il vous permettra de faire à peu près tout ce que vous pouvez concevoir.

Plusieurs occurrences de la variable de liaison apparaissant dans le code SQL sont autorisées. Cependant, vous devrez connaître le nom utilisé en tant que variable de liaison (par exemple: var dans votre cas) pour le transmettre dans DBMS_SQL.BIND_VARIABLE .

Autres conseils

Vous pouvez également contourner ce problème en utilisant une instruction WITH . En général, utiliser DBMS_SQL est préférable, mais parfois, cette méthode est plus simple:

BEGIN
    EXECUTE IMMEDIATE 'WITH var AS (SELECT :var FROM dual) SELECT SYSDATE FROM DUAL WHERE (SELECT * FROM var) = (SELECT * FROM var)' USING 1;
END;

This La discussion sur AskTom couvre le sujet en détail.

Dans votre cas, si vous souhaitez passer un paramètre ou aucun paramètre, vous pouvez créer deux requêtes ayant un seul paramètre et dans l'une de ces requêtes, il n'est pas utilisé (le prédicat est toujours vrai) comme ceci:

-- query1
SELECT * FROM DUAL WHERE dummy = :x;

-- query2
SELECT * FROM DUAL WHERE nvl(:x, 1) IS NOT NULL;

Vous pouvez probablement affiner le prédicat afin que l'optimiseur comprenne qu'il est toujours vrai.

  

Plus précisément, je dois passer un paramètre dans le code SQL inconnu, mais je ne sais pas à quelle fréquence il sera utilisé ici.

En fait, j’ai rencontré le même problème il ya quelques jours et un ami m'a expliqué comment faire exactement cela avec EXECUTE IMMEDIATE .

Il s’agit de générer un bloc PLSQL par opposition au bloc SQL lui-même. Lorsque vous utilisez EXECUTE IMMEDIATE avec un bloc de code PLSQL, vous pouvez lier des variables par nom plutôt que par position.

Découvrez mon exemple / code et sur mon propre fil de questions / réponses similaire:

On peut utiliser dbms_sql comme l'a expliqué Steve Broberg, mais le curseur résultant ne peut pas être utilisé (lu) dans de nombreux clients. Oracle 11 a ajouté une fonction de conversion ( dbms_sql .to_refcursor ) permettant de convertir un curseur dbms_sql en un curseur ref mais, pour une raison quelconque, le curseur ref converti ne peut pas être utilisé dans une application .Net. On peut utiliser un curseur de référence normal dans .net mais pas un curseur de référence qui était auparavant le curseur dbms_sql .

Alors quel type de client utilisera ce curseur?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top