CAS

Pasar parámetros dinámicos a FedSQL en una Acción Personalizada

Simon 24/05/2023 6 vistas

La creación de acciones definidas por el usuario (User-Defined Actions) en SAS© Viya permite encapsular lógica compleja para hacerla reutilizable. Sin embargo, a menudo surge un desafío técnico al intentar anidar código FedSQL dentro de estas definiciones: la gestión de las comillas (quoting) al pasar parámetros (como cadenas de caracteres) en la consulta SQL.

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:

Illustration
1PROC CAS;
2 BUILTINS.defineActionSet /
3 name="tblMakers"
4 actions={
5 {
6 name="tableCreateParam"
7 /* Définition des paramètres attendus par l'action */
8 parms={{name="tblName" type="STRING" required=True}
9 {name="usernameQ" type="STRING" required=True}}
10
11 /* 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 };
19RUN;
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 CASL dentro 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

1/* Astuce : gérer la longueur maximale des chaînes citées si nécessaire */
2%let _sv_quotelenmax=%sysfunc(getoption(quotelenmax));
3options noquotelenmax;
4 
5PROC CAS;
6 BUILTINS.defineActionSet /
7 name="tblMakers"
8 type="CASL"
9 actions={
10 {
11 name="tableCreateParam"
12 parms={ {name="tblName" type="STRING" required=True}
13 {name="whereClause" type="STRING" required=False}
14 }
15 definition=
16 "
17 /* 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 };
28RUN;
29 
30options &_sv_quotelenmax;
Note :
Uso
Este método ofrece total flexibilidad al llamar a la acción:
1PROC 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";
10RUN;

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.