Passer des paramètres dynamiques à FedSQL dans une Action Personnalisée
Simon 42 vistas
Nivel de dificultad
Débutant
Publicado el :
Consejo del experto
Michael
Dans une User-Defined Action, ne voyez pas le code SQL comme un bloc statique, mais comme une variable à construire : exploitez la nature scriptable de CASL pour assembler votre requête dynamiquement par concaténation (||) avant l'exécution. Cette approche modulaire est la seule façon fiable de s'affranchir de l'enfer de l'échappement des caractères ('quoting hell') et de garantir la maintenabilité de vos filtres.
Cet article explore les méthodes pour résoudre ce problème, allant de la simple concaténation à la construction dynamique de clauses WHERE.
Le Problème : La "Soupe" de Guillemets
L'objectif est simple : créer une action CAS qui prend un nom d'utilisateur en paramètre et crée une table filtrée sur ce nom via fedSQL.execDirect.
Le défi réside dans la syntaxe. La définition de l'action est elle-même une chaîne de caractères (souvent entre guillemets doubles). La requête FedSQL est une chaîne à l'intérieur de cette définition (souvent entre guillemets simples). Enfin, la valeur littérale dans le SQL (le nom d'utilisateur) doit être entourée de guillemets simples.
Une tentative naïve échoue souvent car le paramètre n'est pas résolu correctement à l'intérieur de la chaîne littérale de la requête.
Solution 1 : La Concaténation Propre
La méthode la plus robuste pour insérer une variable CASL (le paramètre de votre action) dans la chaîne de requête FedSQL est d'utiliser l'opérateur de concaténation (||) à l'intérieur de la définition.
Il faut "sortir" de la chaîne SQL, concaténer la variable, puis "rentrer" dans la chaîne, tout en s'assurant que les guillemets simples nécessaires au SQL (') sont bien présents.
Exemple de code
Voici comment définir l'action pour qu'elle accepte un paramètre usernameQ et l'insère proprement :
proc cas;
builtins.defineActionSet /
name="tblMakers"
actions={
{
name="tableCreateParam"
/* Définition des paramètres attendus par l'action */
parms={{name="tblName" type="STRING" required=True}
{name="usernameQ" type="STRING" required=True}}
/* La définition utilise la concaténation pour insérer les variables */
definition=
"fedSQL.execDirect / query='create table casuser.'||strip(tblName)||' {options replace=true} as
select userName, TelNum
from CASUSER.have
where userName='''||strip(usernameQ)||''' ';"
}
};
run;
1
PROC CAS;
2
BUILTINS.defineActionSet /
3
name="tblMakers"
4
actions={
5
{
6
name="tableCreateParam"
7
/* Définition des paramètres attendus par l'action */
/* La définition utilise la concaténation pour insérer les variables */
12
definition=
13
"fedSQL.execDirect / query='create TABLE casuser.'||strip(tblName)||' {options replace=true} as
14
select userName, TelNum
15
from CASUSER.have
16
where userName='''||strip(usernameQ)||'''';"
17
}
18
};
19
RUN;
Notez la syntaxe du WHERE : '''||strip(usernameQ)||'''.
Le premier ' ferme la chaîne de la requête SQL.
Les deux ' suivants ('') sont une manière d'échapper un guillemet simple pour qu'il soit interprété comme un littéral par CASL, ce qui résultera en un guillemet ouvrant pour le SQL.
Ensuite vient la variable.
Et enfin la fermeture symétrique.
Solution 2 : Logique Dynamique et Clause WHERE Optionnelle
Une approche plus avancée consiste à utiliser la puissance du langage CASLà l'intérieur de la définition de l'action (definition=...). Puisque la définition contient du code CASL exécutable, vous pouvez utiliser des conditions IF/ELSE pour construire votre requête SQL dynamiquement avant de l'exécuter.
Cela permet, par exemple, de passer une clause WHERE complète ou de la laisser vide.
Exemple de code avancé
/* Astuce : gérer la longueur maximale des chaînes citées si nécessaire */
%let _sv_quotelenmax=%sysfunc(getoption(quotelenmax));
options noquotelenmax;
proc cas;
builtins.defineActionSet /
name="tblMakers"
type="CASL"
actions={
{
name="tableCreateParam"
parms={ {name="tblName" type="STRING" required=True}
{name="whereClause" type="STRING" required=False}
}
definition=
"
/* Logique CASL interne : vérifier si le paramètre existe */
if exists('whereClause') then whereClause=catx(' ','where',whereClause);
else whereClause='';
/* Construction et exécution de la requête */
fedSQL.execDirect / query='create table casuser.'||tblName||' {options replace=true} as
select userName, TelNum
from CASUSER.have '||whereClause||' ';
"
}
};
run;
options &_sv_quotelenmax;
1
/* Astuce : gérer la longueur maximale des chaînes citées si nécessaire */
/* Logique CASL interne : vérifier si le paramètre existe */
18
if exists('whereClause') then whereClause=catx('','where',whereClause);
19
else whereClause='';
20
21
/* Construction et exécution de la requête */
22
fedSQL.execDirect / query='create TABLE casuser.'||tblName||' {options replace=true} as
23
select userName, TelNum
24
from CASUSER.have '||whereClause||'';
25
"
26
}
27
};
28
RUN;
29
30
options &_sv_quotelenmax;
Note : Utilisation
Cette méthode offre une flexibilité totale lors de l'appel de l'action :
proc cas;
/* Appel avec un filtre complexe */
tblMakers.tableCreateParam /
tblName="resultat1"
whereClause="userName='User 1' or TelNum = 333333";
/* Appel sans filtre (crée une copie complète) */
tblMakers.tableCreateParam /
tblName="resultat2";
run;
1
PROC CAS;
2
/* Appel avec un filtre complexe */
3
tblMakers.tableCreateParam /
4
tblName="resultat1"
5
whereClause="userName='User 1' or TelNum = 333333";
6
7
/* Appel sans filtre (crée une copie complète) */
8
tblMakers.tableCreateParam /
9
tblName="resultat2";
10
RUN;
L'intégration de FedSQL dans les actions définies par l'utilisateur ne nécessite pas de manipulations de chaînes illisibles. En utilisant l'opérateur de concaténation || et en tirant parti de la capacité du paramètre definition à exécuter de la logique CASL (comme if exists), vous pouvez créer des actions robustes, lisibles et hautement paramétrables.
Aviso importante
Los códigos y ejemplos proporcionados en WeAreCAS.eu son con fines educativos. Es imperativo no copiarlos y pegarlos ciegamente en sus entornos de producción. El mejor enfoque es comprender la lógica antes de aplicarla. Recomendamos encarecidamente probar estos scripts en un entorno de prueba (Sandbox/Dev). WeAreCAS no acepta ninguna responsabilidad por cualquier impacto o pérdida de datos en sus sistemas.
SAS y todos los demás nombres de productos o servicios de SAS Institute Inc. son marcas registradas o marcas comerciales de SAS Institute Inc. en los EE. UU. y otros países. ® indica registro en los EE. UU. WeAreCAS es un sitio comunitario independiente y no está afiliado a SAS Institute Inc.
Este sitio utiliza cookies técnicas y analíticas para mejorar su experiencia.
Saber más.