Като цяло единични, кавичките се избягват чрез удвояването им.
За да свържете вашите променливи в SQL низ, трябва да използвате quote_literal()
- тази функция се грижи за правилното избягване на единични кавички, напр.:
quote_literal(temp_row.row_data)
Като каза това:по-доброто (и по-безопасно) решение е да се използват параметри, комбинирани с format()
:
EXECUTE
format('INSERT INTO audit.%I_history values ($1, $2, $3)', tg_table_name)
using temp_row.action_tstamp_tx, temp_row.action, temp_row.row_data;
%I
placeholder обикновено се грижи за правилното екраниране на идентификатор, въпреки че в този случай няма да работи. Ако искате да сте 100% сигурни, че дори нестандартните имена на таблици работят правилно, трябва първо да поставите името на целевата таблица в променлива и да го използвате за format()
функция:
l_tablename := TG_TABLE_NAME || '_history';
EXECUTE
format('INSERT INTO audit.%I_history values ($1, $2, $3)', l_tablename)
using ....
Тази част:
v_sql = 'select * from ' || TG_TABLE_NAME::regclass || '_history';
execute v_sql into temp_row;
ще се провали и след първия ред. execute .. into ...
очаква заявката да върне единичен . Изявлението, което използвате, ще върне всички редове от таблицата с история.
Също така не разбирам защо го правиш на първо място.
Изобщо не е необходимо да избирате от таблицата с хронологията.
Нещо подобно би трябвало да е достатъчно (нетествано! ):
IF (TG_OP = 'UPDATE' AND TG_LEVEL = 'ROW') THEN
temp_row := OLD;
ELSIF (TG_OP = 'DELETE' AND TG_LEVEL = 'ROW') THEN
temp_row := OLD;
ELSIF (TG_OP = 'INSERT' AND TG_LEVEL = 'ROW') THEN
temp_row := NEW;
ELSE
RAISE EXCEPTION '[audit.if_modified] - Trigger func added as trigger for unhandled case: %, %',TG_OP, TG_LEVEL;
RETURN NULL;
END IF;
execute format ('insert ... values ($1, $2, $3')
using now(), SUBSTRING(TG_OP,1,1), temp_row;
И накрая:тригерите за одит са писани преди и има много готови решения за това: