Passing Dynamic Parameters to FedSQL in a Custom Action
Simon 43 vues
Niveau de difficulté
Débutant
Publié le :
Le conseil de l'expert
Simon
Successfully embedding FedSQL within a Custom Action hinges on resolving the nested quote syntax ("Quote Soup"). To secure your dynamic parameters, move away from static strings and embrace CASL logic construction: leverage the concatenation operator (||) and rigorous escaping ('') to assemble your SQL queries programmatically before execution.
This article explores methods to solve this problem, ranging from simple concatenation to the dynamic construction of WHERE clauses.
The Problem: The "Quote Soup"
The objective is simple: create a CAS action that takes a username as a parameter and creates a table filtered on that name via fedSQL.execDirect.
The challenge lies in the syntax. The action definition itself is a character string (often in double quotes). The FedSQL query is a string within that definition (often in single quotes). Finally, the literal value in the SQL (the username) must be enclosed in single quotes.
A naive attempt often fails because the parameter is not resolved correctly within the literal string of the query.
Solution 1: Clean Concatenation
The most robust method for inserting a CASL variable (your action's parameter) into the FedSQL query string is to use the concatenation operator (||) inside the definition.
You need to "exit" the SQL string, concatenate the variable, then "re-enter" the string, all while ensuring that the single quotes required for SQL (') are present.
Code Example
Here's how to define the action so that it accepts a usernameQ parameter and inserts it cleanly:
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;
Note the WHERE syntax: '''||strip(usernameQ)||'''.
The first ' closes the SQL query string.
The next two '' are a way to escape a single quote so that it is interpreted as a literal by CASL, which will result in an opening quote for SQL.
Then comes the variable.
And finally the symmetrical closing.
Solution 2: Dynamic Logic and Optional WHERE Clause
A more advanced approach is to use the power of the CASL language inside the action definition (definition=...). Since the definition contains executable CASL code, you can use IF/ELSE conditions to build your SQL query dynamically before executing it.
This allows, for example, to pass a complete WHERE clause or to leave it empty.
Advanced Code Example
/* 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 : Usage
This method offers complete flexibility when calling the 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;
Integrating FedSQL into user-defined actions does not require unreadable string manipulations. By using the concatenation operator || and leveraging the definition parameter's ability to execute CASL logic (like if exists), you can create robust, readable, and highly parametrizable actions.
Avertissement important
Les codes et exemples fournis sur WeAreCAS.eu sont à but pédagogique. Il est impératif de ne pas les copier-coller aveuglément sur vos environnements de production. La meilleure approche consiste à comprendre la logique avant de l'appliquer. Nous vous recommandons vivement de tester ces scripts dans un environnement de test (Sandbox/Dev). WeAreCAS décline toute responsabilité quant aux éventuels impacts ou pertes de données sur vos systèmes.
SAS et tous les autres noms de produits ou de services de SAS Institute Inc. sont des marques déposées ou des marques de commerce de SAS Institute Inc. aux États-Unis et dans d'autres pays. ® indique un enregistrement aux États-Unis. WeAreCAS est un site communautaire indépendant et n'est pas affilié à SAS Institute Inc.
Ce site utilise des cookies techniques et analytiques pour améliorer votre expérience.
En savoir plus.