PSQL SET
variabler interpoleras inte i strängar med noterade dollar. Jag vet inte detta med säkerhet, men jag tror att det inte finns någon flykt eller andra knep för att aktivera SET
variabel interpolation där.
Man skulle kunna tro att du kunde kila in en :user
utan citat mellan två dollarnoterade sträckor av PL/pgSQL för att få önskad effekt. Men det här verkar inte fungera... Jag tror att syntaxen kräver en enda sträng och inte ett uttryck som sammanfogar strängar. Kan ha fel i det.
Hur som helst, det spelar ingen roll. Det finns ett annat tillvägagångssätt (som Pasco noterade):skriv den lagrade proceduren för att acceptera ett PL/pgSQL-argument. Så här skulle det se ut.
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;
Anmärkningar om denna funktion:
EXECUTE
genererar en lämpligGRANT
på varje anrop med hjälp av vårt procedurargument. PG-manualavsnittet som heter "Executing Dynamic Commands " förklararEXECUTE
i detalj.- Procedurdeklarationens argument
user
måste vara dubbla citattecken. Dubbla citattecken tvingar den att tolkas som en identifierare.
När du väl har definierat funktionen så här kan du anropa den med hjälp av interpolerade PSQL-variabler. Här är en översikt.
- Kör
psql --variable user="'whoever'" --file=myscript.sql
. Enstaka citattecken krävs runt användarnamnet! - I myscript.sql, definiera funktion som ovan.
- I myscript.sql, sätt
select foo(:user);
. Det är här vi förlitar oss på de enskilda citattecken som vi sätter i värdet föruser
.
Även om det här verkar fungera så tycker jag det är ganska skumt. Jag tänkte SET
variabler var avsedda för körtidskonfiguration. Bär data runt i SET
verkar konstigt.
Redigera :här är en konkret anledning att inte använd SET
variabler. Från manpage:"Dessa uppdrag görs under ett mycket tidigt skede av uppstart, så variabler reserverade för interna ändamål kan skrivas över senare." Om Postgres bestämde sig för att använda en variabel med namnet user
(eller vad du än väljer), det kan skriva över ditt manusargument med något du aldrig hade tänkt dig. Faktum är att psql redan tar USER
för sig själv -- detta fungerar bara eftersom SET
är skiftlägeskänslig. Detta gjorde nästan sönder saker från början!