PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Да дефинирате имената на таблици и колони като аргументи във функцията plpgsql?

Трябва да се защитавате срещу 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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. вземете последните три месеца записи от таблицата

  2. Как да създадете индекс за елементи от масив в PostgreSQL?

  3. PostgreSQL - максимален брой параметри в IN клауза?

  4. Къде са регистрационните файлове на PostgreSQL в macOS?

  5. Може ли PostgreSQL да извърши свързване между две съхранени процедури на SQL Server?