Passer des paramètres dynamiques à FedSQL dans une Action Personnalisée
Simon 42 Aufrufe
Schwierigkeitsgrad
Débutant
Veröffentlicht am :
Expertenrat
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.
Wichtiger Haftungsausschluss
Die auf WeAreCAS.eu bereitgestellten Codes und Beispiele dienen Lehrzwecken. Es ist zwingend erforderlich, sie nicht blind in Ihre Produktionsumgebungen zu kopieren. Der beste Ansatz besteht darin, die Logik zu verstehen, bevor sie angewendet wird. Wir empfehlen dringend, diese Skripte in einer Testumgebung (Sandbox/Dev) zu testen. WeAreCAS übernimmt keine Verantwortung für mögliche Auswirkungen oder Datenverluste auf Ihren Systemen.
SAS und alle anderen Produkt- oder Dienstleistungsnamen von SAS Institute Inc. sind eingetragene Marken oder Marken von SAS Institute Inc. in den USA und anderen Ländern. ® zeigt die Registrierung in den USA an. WeAreCAS ist eine unabhängige Community-Site und nicht mit SAS Institute Inc. verbunden.
Diese Website verwendet technische und analytische Cookies, um Ihre Erfahrung zu verbessern.
Mehr erfahren.