sql >> Database teknologi >  >> RDS >> PostgreSQL

Definer tabel- og kolonnenavne som argumenter i en plpgsql-funktion?

Du skal forsvare dig mod SQL-injektion hver gang du omdanner brugerinput til kode. Det inkluderer tabel- og kolonnenavne, der kommer fra systemkataloger eller fra direkte brugerinput. På denne måde forhindrer du også trivielle undtagelser med ikke-standardiserede identifikatorer. Der er grundlæggende tre indbyggede metoder:

1. format()

1. forespørgsel, renset:

CREATE OR REPLACE FUNCTION foo(_t text)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format('
   ALTER TABLE %I ADD COLUMN c1 varchar(20)
                , ADD COLUMN c2 varchar(20)', _t);
END
$func$;

format() kræver Postgres 9.1 eller nyere. Brug den med %I formatspecifikation.

Alene tabelnavnet kan være tvetydigt. Du skal muligvis angive skemanavnet for at undgå at ændre den forkerte tabel ved et uheld. Relateret:

  • INSERT med dynamisk tabelnavn i triggerfunktion
  • Hvordan påvirker søgestien identifikationsopløsning og det "aktuelle skema"

Til side:Tilføjelse af flere kolonner med en enkelt ALTER TABLE kommandoen er billigere.

2. regclass

Du kan også bruge en cast til en registreret klasse (regclass ) for det særlige tilfælde eksisterende tabelnavne. Eventuelt skema-kvalificeret. Dette mislykkes øjeblikkeligt og elegant for tabelnavne, der ikke er gyldige og synlige for den kaldende bruger. Den første forespørgsel blev renset med en cast til regclass :

CREATE OR REPLACE FUNCTION foo(_t regclass)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE 'ALTER TABLE ' || _t || ' ADD COLUMN c1 varchar(20)
                                   , ADD COLUMN c2 varchar(20)';
END
$func$;

Ring til:

SELECT foo('table_name');

Eller:

SELECT foo('my_schema.table_name'::regclass);

Til side:Overvej kun at bruge text i stedet for varchar(20) .

3. quote_ident()

Den 2. forespørgsel renset:

CREATE OR REPLACE FUNCTION foo(_t regclass, _c text)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE 'UPDATE ' || _t    -- sanitized with regclass
        || ' SET ' || quote_ident(_c) || ' = ''This is a test''';
END
$func$;

For flere sammenkædninger/interpolationer, format() er renere ...

Relaterede svar:

  • Tabelnavn som en PostgreSQL-funktionsparameter
  • Postgres-funktioner kontra forberedte forespørgsler

Der skelnes mellem store og små bogstaver!

Vær opmærksom på, at identifikatorer uden anførsel ikke er støbt til små bogstaver her. Når det bruges som identifikator i SQL [Postgres kaster automatisk til små bogstaver][7]. Men her passerer vi strenge til dynamisk SQL. Når escaped som vist, CaMel-case identifikatorer (som UserS ) vil blive bevaret ved dobbeltcitering ("UserS" ), ligesom andre ikke-standardnavne som "name with space" "SELECT" osv. Derfor skelnes der mellem store og små bogstaver i navne i denne sammenhæng.

Mit stående råd er udelukkende at bruge lovlige små bogstaver og aldrig bekymre dig om det.

Bortset fra:Enkelte anførselstegn er for værdier, dobbelte anførselstegn er for identifikatorer. Se:

  • https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS



  1. Sådan installeres Oracle SQL Developer 18.2 på Windows 10?

  2. Salesforce SOQL fra Apache OpenOffice

  3. Hvordan ser man CREATE VIEW-koden for en visning i PostgreSQL?

  4. Hvordan får man alle værdier i en kolonne ved hjælp af PHP?