Musisz bronić się przed wstrzyknięciem SQL za każdym razem, gdy zamieniasz dane wprowadzone przez użytkownika w kod. Obejmuje to nazwy tabel i kolumn pochodzące z katalogów systemowych lub z bezpośrednich danych wejściowych użytkownika. W ten sposób zapobiegasz również trywialnym wyjątkom z niestandardowymi identyfikatorami. Zasadniczo są trzy wbudowane metody:
1. format()
Pierwsze zapytanie, oczyszczone:
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()
wymaga Postgresa 9.1 lub nowszego. Użyj go z %I
specyfikator formatu.
Sama nazwa tabeli może być niejednoznaczna. Być może będziesz musiał podać nazwę schematu, aby uniknąć przypadkowej zmiany niewłaściwej tabeli. Powiązane:
- WSTAW z dynamiczną nazwą tabeli w funkcji wyzwalacza
- W jaki sposób search_path wpływa na rozpoznawanie identyfikatora i „bieżący schemat”
Na bok:dodawanie wielu kolumn z jedną ALTER TABLE
polecenie jest tańsze.
2. regclass
Możesz także użyć rzutowania na zarejestrowaną klasę (regclass
) dla szczególnego przypadku istniejącego nazwy tabel. Opcjonalnie kwalifikowana schematem. To kończy się niepowodzeniem natychmiast i wdzięcznie w przypadku nazw tabel, które nie są prawidłowe i widoczne dla użytkownika wywołującego. Pierwsze zapytanie oczyszczone za pomocą rzutowania do 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$;
Zadzwoń:
SELECT foo('table_name');
Lub:
SELECT foo('my_schema.table_name'::regclass);
Na bok:rozważ użycie tylko text
zamiast varchar(20)
.
3. quote_ident()
Oczyszczone drugie zapytanie:
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$;
Dla wielu konkatenacji / interpolacji, format()
jest czystszy ...
Powiązane odpowiedzi:
- Nazwa tabeli jako parametr funkcji PostgreSQL
- Funkcje Postgres a przygotowane zapytania
Rozróżniana wielkość liter!
Pamiętaj, że niecytowane identyfikatory nie oddaj tutaj małe litery. W przypadku użycia jako identyfikator w SQL [Postgres automatycznie odwzorowuje małe litery][7]. Ale tutaj przekazujemy stringi dla dynamicznego SQL. Po opuszczeniu, jak pokazano, identyfikatory CaMel-case (takie jak UserS
) zostanie zachowany przez podwójne cudzysłowy ("UserS"
), podobnie jak inne niestandardowe nazwy, takie jak "name with space"
"SELECT"
itp. W związku z tym w nazwach rozróżniana jest wielkość liter.
Moją stałą radą jest używanie wyłącznie prawnych identyfikatorów małymi literami i nie martw się o to.
Poza tym:pojedyncze cudzysłowy dotyczą wartości, podwójne cudzysłowy dotyczą identyfikatorów. Zobacz:
- https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS