CAS

Dynamische Parameter an FedSQL in einer benutzerdefinierten Aktion übergeben

Simon 24/05/2023 6 views

Die Erstellung benutzerdefinierter Aktionen (User-Defined Actions) in SAS© Viya ermöglicht die Kapselung komplexer Logik zur Wiederverwendung. Oft tritt jedoch eine technische Herausforderung auf, wenn versucht wird, FedSQL-Code in diese Definitionen einzubetten: die Handhabung von Anführungszeichen (Quoting) beim Übergeben von Parametern (wie Zeichenketten) in der SQL-Abfrage.

Dieser Artikel untersucht Methoden zur Lösung dieses Problems, von der einfachen Verkettung bis zur dynamischen Konstruktion von WHERE-Klauseln.

Das Problem: Der "Anführungszeichen-Salat"

Das Ziel ist einfach: eine CAS-Aktion zu erstellen, die einen Benutzernamen als Parameter annimmt und eine Tabelle filtert, die auf diesem Namen basiert, über fedSQL.execDirect.

Die Herausforderung liegt in der Syntax. Die Aktionsdefinition selbst ist eine Zeichenkette (oft in doppelten Anführungszeichen). Die FedSQL-Abfrage ist eine Zeichenkette innerhalb dieser Definition (oft in einfachen Anführungszeichen). Schließlich muss der Literalwert in SQL (der Benutzername) in einfachen Anführungszeichen stehen.

Ein naiver Versuch schlägt oft fehl, da der Parameter innerhalb der literalisierten Abfragezeichenkette nicht korrekt aufgelöst wird.

Lösung 1: Die saubere Verkettung

Die robusteste Methode, um eine CASL-Variable (den Parameter Ihrer Aktion) in die FedSQL-Abfragezeichenkette einzufügen, ist die Verwendung des Verkettungsoperators (||) innerhalb der Definition.

Man muss die SQL-Zeichenkette verlassen, die Variable verketten und dann wieder in die Zeichenkette eintreten, wobei sichergestellt werden muss, dass die für SQL erforderlichen einfachen Anführungszeichen (') vorhanden sind.

Codebeispiel

So definieren Sie die Aktion, damit sie einen Parameter usernameQ akzeptiert und ihn korrekt einfügt:

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;
Beachten Sie die WHERE-Syntax: '''||strip(usernameQ)||'''.

Das erste ' schließt die SQL-Abfragezeichenkette.

Die nächsten beiden '' sind eine Möglichkeit, ein einfaches Anführungszeichen zu maskieren, damit es von CASL als Literal interpretiert wird, was zu einem öffnenden Anführungszeichen für SQL führt.

Dann kommt die Variable.

Und schließlich die symmetrische Schließung.

Lösung 2: Dynamische Logik und optionale WHERE-Klausel

Ein fortgeschrittenerer Ansatz besteht darin, die Leistungsfähigkeit der CASL-Sprache innerhalb der Aktionsdefinition (definition=...) zu nutzen. Da die Definition ausführbaren CASL-Code enthält, können Sie IF/ELSE-Bedingungen verwenden, um Ihre SQL-Abfrage vor der Ausführung dynamisch zu erstellen.

Dies ermöglicht es beispielsweise, eine vollständige WHERE-Klausel zu übergeben oder sie leer zu lassen.

Beispiel für erweiterten Code

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 :
Verwendung
Diese Methode bietet bei Aufruf der Aktion volle Flexibilität:
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;

Die Integration von FedSQL in benutzerdefinierte Aktionen erfordert keine unleserlichen Zeichenkettenmanipulationen. Durch die Verwendung des Verkettungsoperators || und die Nutzung der Fähigkeit des definition-Parameters, CASL-Logik (wie if exists) auszuführen, können Sie robuste, lesbare und hochgradig parametrierbare Aktionen erstellen.