Este artículo explora los métodos para resolver este problema, desde la simple concatenación hasta la construcción dinámica de cláusulas WHERE.
El Problema: La "Sopa" de Comillas
El objetivo es simple: crear una acción CAS que tome un nombre de usuario como parámetro y cree una tabla filtrada por ese nombre a través de fedSQL.execDirect.
El desafío reside en la sintaxis. La definición de la acción es en sí misma una cadena de caracteres (a menudo entre comillas dobles). La consulta FedSQL es una cadena dentro de esta definición (a menudo entre comillas simples). Finalmente, el valor literal en SQL (el nombre de usuario) debe ir entre comillas simples.
Un intento ingenuo a menudo falla porque el parámetro no se resuelve correctamente dentro de la cadena literal de la consulta.
Solución 1: La Concatenación Limpia
El método más robusto para insertar una variable CASL (el parámetro de su acción) en la cadena de consulta FedSQL es usar el operador de concatenación (||) dentro de la definición.
Hay que "salir" de la cadena SQL, concatenar la variable y luego "volver a entrar" en la cadena, asegurándose de que las comillas simples necesarias para SQL (') estén presentes.
Ejemplo de código
Aquí se explica cómo definir la acción para que acepte un parámetro usernameQ y lo inserte correctamente:
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;
Tenga en cuenta la sintaxis de WHERE: '''||strip(usernameQ)||'''.
El primer ' cierra la cadena de la consulta SQL.
Los dos ' siguientes ('') son una forma de escapar una comilla simple para que CASL la interprete como un literal, lo que resultará en una comilla de apertura para SQL.
Luego viene la variable.
Y finalmente el cierre simétrico.
Solución 2: Lógica Dinámica y Cláusula WHERE Opcional
Un enfoque más avanzado consiste en usar la potencia del lenguaje CASLdentro de la definición de la acción (definition=...). Dado que la definición contiene código CASL ejecutable, puede usar condiciones IF/ELSE para construir su consulta SQL dinámicamente antes de ejecutarla.
Esto permite, por ejemplo, pasar una cláusula WHERE completa o dejarla vacía.
Ejemplo de código avanzado
/* 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 : Uso
Este método ofrece total flexibilidad al llamar a la acción:
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;
La integración de FedSQL en las acciones definidas por el usuario no requiere manipulaciones de cadenas ilegibles. Al usar el operador de concatenación || y aprovechar la capacidad del parámetro definition para ejecutar lógica CASL (como if exists), puede crear acciones robustas, legibles y altamente parametrizables.
Important Disclaimer
The codes and examples provided on WeAreCAS.eu are for educational purposes. It is imperative not to blindly copy-paste them into your production environments. The best approach is to understand the logic before applying it. We strongly recommend testing these scripts in a test environment (Sandbox/Dev). WeAreCAS accepts no responsibility for any impact or data loss on your systems.
SAS and all other SAS Institute Inc. product or service names are registered trademarks or trademarks of SAS Institute Inc. in the USA and other countries. ® indicates USA registration. WeAreCAS is an independent community site and is not affiliated with SAS Institute Inc.
This site uses technical and analytical cookies to improve your experience.
Read more.