PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Gibt es eine Escape-Syntax für die psql-Variable in PostgreSQL-Funktionen?

PSQL SET Variablen werden nicht innerhalb von Zeichenfolgen in Dollar-Anführungszeichen interpoliert. Ich weiß es nicht genau, aber ich denke, es gibt keinen Ausweg oder andere Tricks, um SET einzuschalten Variable Interpolation drin.

Man könnte meinen, Sie könnten einen nicht in Anführungszeichen gesetzten :user einklemmen zwischen zwei in Dollar notierten Abschnitten von PL/pgSQL, um den gewünschten Effekt zu erzielen. Aber das scheint nicht zu funktionieren ... Ich denke, die Syntax erfordert eine einzelne Zeichenfolge und keinen Ausdruck, der Zeichenfolgen verkettet. Könnte mich da irren.

Jedenfalls spielt das keine Rolle. Es gibt einen anderen Ansatz (wie Pasco bemerkte):Schreiben Sie die gespeicherte Prozedur, um ein PL/pgSQL-Argument zu akzeptieren. So würde das aussehen.

CREATE OR REPLACE FUNCTION foo("user" TEXT) RETURNS void AS
$$
BEGIN
        EXECUTE 'GRANT SELECT ON my_table TO GROUP ' || quote_ident(user);
END;    
$$ LANGUAGE plpgsql;

Hinweise zu dieser Funktion:

  1. EXECUTE generiert einen entsprechenden GRANT bei jedem Aufruf mit unserem Prozedurargument. Der Abschnitt des PG-Handbuchs namens „Dynamische Befehle ausführen " erklärt EXECUTE ausführlich.
  2. Die Deklaration des Prozedurarguments user muss in doppelte Anführungszeichen gesetzt werden. Doppelte Anführungszeichen erzwingen die Interpretation als Bezeichner.

Sobald Sie die Funktion so definiert haben, können Sie sie mit interpolierten PSQL-Variablen aufrufen. Hier ist eine Gliederung.

  1. Führen Sie psql --variable user="'whoever'" --file=myscript.sql aus . Der Benutzername muss in einfache Anführungszeichen gesetzt werden!
  2. Definieren Sie in myscript.sql die Funktion wie oben.
  3. Fügen Sie in myscript.sql select foo(:user); ein . Hier verlassen wir uns auf die einfachen Anführungszeichen, die wir in den Wert von user setzen .

Obwohl dies zu funktionieren scheint, kommt es mir ziemlich squirrly vor. Ich dachte SET Variablen waren für die Laufzeitkonfiguration vorgesehen. Daten in SET herumtragen scheint seltsam.

Bearbeiten :Hier ist ein konkreter Grund, es nicht zu tun Verwenden Sie SET Variablen. Aus der Manpage:"Diese Zuweisungen werden in einer sehr frühen Phase des Starts vorgenommen, sodass Variablen, die für interne Zwecke reserviert sind, später möglicherweise überschrieben werden." Wenn Postgres sich entschieden hat, eine Variable namens user zu verwenden (oder was auch immer Sie wählen), es könnte Ihr Skriptargument mit etwas überschreiben, das Sie nie beabsichtigt haben. Tatsächlich nimmt psql bereits USER für sich selbst – das funktioniert nur, weil SET unterscheidet zwischen Groß- und Kleinschreibung. Das hätte fast von Anfang an alles kaputt gemacht!