Динамичен достъп до стойността на колоната в записа

Възможно ли е динамичен достъп до стойност на колона от запис по нейното име?

Пиша тригерна функция, която изпълнява динамична SQL команда и бих искал динамично да извлека стойност на колона от NEW запис по име на колона.

Ето опростен пример за това, което се опитвам да направя:

$$
DECLARE
   command text := 'UPDATE $1 SET $2 = $3';
   myColumn := 'votes'
BEGIN
   EXECUTE command using 'anotherTable', myColumn, NEW.myColumn;
END
$$

person Juan Jose Lenero Lozano    schedule 09.09.2015    source източник


Отговори (1)


Това е възможно, но клаузата USING на EXECUTE може да предава само стойности.
Докато идентификаторите като имена на таблици и колони трябва да бъдат свързани (внимавайте с SQL инжектиране!) преди да изпълните командата. Използване на format()< /a> (Postgres 9.1+) може да работи така:

$$
DECLARE
   _command text := 'UPDATE %I SET %I = $1 WHERE ....'; -- add WHERE condition
   _col text := 'votes';
BEGIN
   EXECUTE format(_command, 'anotherTable', _col)
   USING  NEW.myColumn;
END
$$;

Коригирани са няколко дребни проблема при преминаване.

Трябва да се спомене, че NEW е наличен само в тригерни функции.

Имайте предвид, че 'anotherTable' е чувствителен към малки и малки букви тук (преобразува се и се екранира от низ), докато NEW.myColumn не е (обработва се като идентификатор). Използвайте законни идентификатори с малки букви и без кавички в Postgres, за да улесните живота си.

Свързани отговори с повече обяснения и връзки:


За динамично извличане на стойност на колона от NEW запис по име на колона.

... можете да използвате hstore #= оператор:

Или можете да го накарате да работи и със стандартните функции на динамичния SQL:

$$
DECLARE
   _col text := 'votes';
   _new_col text := 'column_name_in_new';  -- enter column name here, case sensitive
BEGIN
   EXECUTE format(
       'UPDATE %I SET %I = $1.%I WHERE ... '  -- add WHERE condition
     , 'anotherTable', _col, _new_col)
   USING  NEW;  -- pass whole row
END
$$;

Свързани:

person Erwin Brandstetter    schedule 09.09.2015
comment
Благодаря за страхотния отговор, но това все още не е точно това, което се опитвах да направя. Във вашия пример вие изрично осъществихте достъп до NEW.myColumn; Бих искал да осъществя динамичен достъп до колона въз основа на предварително съществуваща стойност, нещо като NEW[_column]. Някой предложи другаде да се използва hstore. Това работи: hstore(NEW)->_column за динамичен достъп до колоната гласове в NEW. Въпреки това изобщо не съм запознат с hstore и бих предпочел да не активирам разширението, ако има по-проста алтернатива. - person Juan Jose Lenero Lozano; 10.09.2015
comment
@RedHusky: Добавих друго решение за това. - person Erwin Brandstetter; 10.09.2015