sql >> Databáze >  >> RDS >> PostgreSQL

Definovat názvy tabulek a sloupců jako argumenty ve funkci plpgsql?

Musíte se bránit vložení SQL kdykoli změníte uživatelský vstup na kód. To zahrnuje názvy tabulek a sloupců pocházející ze systémových katalogů nebo z přímého uživatelského vstupu. Předejdete tak i triviálním výjimkám s nestandardními identifikátory. V zásadě jsoutři vestavěné metody:

1. format()

1. dotaz, vyčištěno:

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() vyžaduje Postgres 9.1 nebo novější. Použijte jej s %I specifikátor formátu.

Samotný název tabulky může být nejednoznačný. Možná budete muset zadat název schématu, abyste se vyhnuli náhodné změně nesprávné tabulky. Související:

  • INSERT s názvem dynamické tabulky ve funkci spouštění
  • Jak parametr search_path ovlivňuje rozlišení identifikátoru a "aktuální schéma"

Stranou:přidání více sloupců s jedinou ALTER TABLE příkaz je levnější.

2. regclass

Můžete také použít obsazení do registrované třídy (regclass ) pro zvláštní případ existující názvy tabulek. Volitelně kvalifikováno pro schéma. To selže okamžitě a bez chyb u názvů tabulek, které nejsou platné a viditelné pro volajícího uživatele. První dotaz byl vyčištěn přetypováním na 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$;

Volejte:

SELECT foo('table_name');

Nebo:

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

Stranou:zvažte použití pouze text místo varchar(20) .

3. quote_ident()

2. dotaz byl vyčištěn:

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$;

Pro vícenásobné zřetězení / interpolace použijte format() je čistší ...

Související odpovědi:

  • Název tabulky jako parametr funkce PostgreSQL
  • Funkce Postgres vs. připravené dotazy

Rozlišují se malá a velká písmena!

Uvědomte si, že neuvedené identifikátory nejsou zde přehodit na malá písmena. Při použití jako identifikátor v SQL [Postgres přetypuje na malá písmena automaticky][7]. Ale tady předáváme řetězce pro dynamické SQL. Při escapování, jak je ukázáno, identifikátory CaMel-case (jako UserS ) budou zachovány dvojitými uvozovkami ("UserS" ), stejně jako ostatní nestandardní názvy jako "name with space" "SELECT" atd. U jmen se tedy v tomto kontextu rozlišují velká a malá písmena.

Moje stálá rada je používat výhradně legální malá písmena a nikdy si s tím nedělejte starosti.

Stranou:jednoduché uvozovky jsou pro hodnoty, dvojité uvozovky jsou pro identifikátory. Viz:

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



  1. Jak nainstalovat a nakonfigurovat phpMyAdmin na CentOS 6

  2. Jaký je nejlepší způsob předání parametrů SQLCommand?

  3. Jak překonat náhodné smazání dat v MySQL a MariaDB

  4. Snímky databáze SQL Server -3