sql >> Databasteknik >  >> RDS >> PostgreSQL

Finns det någon escape-syntax för psql-variabel inuti PostgreSQL-funktioner?

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:

  1. EXECUTE genererar en lämplig GRANT på varje anrop med hjälp av vårt procedurargument. PG-manualavsnittet som heter "Executing Dynamic Commands " förklarar EXECUTE i detalj.
  2. 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.

  1. Kör psql --variable user="'whoever'" --file=myscript.sql . Enstaka citattecken krävs runt användarnamnet!
  2. I myscript.sql, definiera funktion som ovan.
  3. 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ör user .

Ä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!



  1. diff 2 stora databastabeller

  2. begränsa fältets värde med värde från en annan tabell före skrivning

  3. Räkna och gruppera icke-tomma värden i MySQL

  4. Hur man grupperar efter 1 i SQL Server