Трябва да се защитавате срещу SQL инжекция всеки път, когато превръщате въведеното от потребителя в код. Това включва имена на таблици и колони, идващи от системни каталози или от директно въвеждане на потребителя. По този начин също така предотвратявате тривиални изключения с нестандартни идентификатори. По принцип сатри вградени методи:
1. format()
1-ва заявка, дезинфекцирана:
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()
изисква Postgres 9.1 или по-нова версия. Използвайте го с %I
спецификатор на формат.
Самото име на таблицата може да е двусмислено. Може да се наложи да предоставите името на схемата, за да избегнете случайна промяна на грешната таблица. Свързано:
- INSERT с динамично име на таблица в тригерна функция
- Как search_path влияе върху разделителната способност на идентификатора и „текущата схема“
Настрана:добавяне на множество колони с един ALTER TABLE
командата е по-евтина.
2. regclass
Можете също да използвате прехвърляне към регистриран клас (regclass
) за специалния случай насъществуващ имена на таблици. По избор квалифицирани по схема. Това се проваля незабавно и изящно за имена на таблици, които не са валидни и видими за повикващия потребител. Първата заявка е санирана с прехвърляне към 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$;
Обадете се:
SELECT foo('table_name');
Или:
SELECT foo('my_schema.table_name'::regclass);
Настрана:помислете за използването само на text
вместо varchar(20)
.
3. quote_ident()
Втората заявка е санирана:
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$;
За множество конкатенации / интерполации, format()
е по-чисто...
Свързани отговори:
- Име на таблица като параметър на функцията на PostgreSQL
- Функции на Postgres срещу подготвени заявки
Регистърът на буквите е чувствителен!
Имайте предвид, че идентификаторите без кавички не прехвърляне на малки букви тук. Когато се използва като идентификатор в SQL [Postgres прехвърля автоматично към малки букви] [7]. Но тук предаваме низове за динамичен SQL. Когато се екранират, както е показано, CaMel-case идентификатори (като UserS
) ще бъде запазен чрез двойни кавички ("UserS"
), точно както други нестандартни имена като "name with space"
"SELECT"
и т.н. Следователно имената са чувствителни към малки и големи букви в този контекст.
Моят постоянен съвет е да използвате изключително законни идентификатори с малки букви и никога да не се притеснявате за това.
Настрана:единичните кавички са за стойности, двойните кавички са за идентификатори. Вижте:
- https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS