@romaro

Как в Postgres запустить выражение, которое существует в виде строки?

В Oracle все просто:
l_sql := '...sql...';
	execute immediate l_sql;


В PG конечно попробовал так:
DECLARE
		l_sql	text;
	BEGIN
		l_sql := 'ALTER TYPE obj_name_tp ADD VALUE IF NOT EXISTS '||chr(39)||l_table_name||chr(39)||';';
		EXECUTE IMMEDIATE l_sql;
	END;


Потом так:
EXEC SQL BEGIN DECLARE SECTION;
		const char *l_sql = 'ALTER TYPE obj_name_tp ADD VALUE IF NOT EXISTS '||chr(39)||l_table_name||chr(39)||';';
	EXEC SQL END DECLARE SECTION;

	EXEC SQL EXECUTE IMMEDIATE :l_sql;


И даже так (тут видимо не работает, потому что ALTER TYPE не подходит под допустимые операторы):
PREPARE add_to_type (varchar) AS
    	ALTER TYPE obj_name_tp ADD VALUE IF NOT EXISTS $1;
	EXECUTE add_to_type(l_table_name);


Наконец, пробую так:
DECLARE
    l_table_name	varchar(30) := lower(p_table_name);
BEGIN
	EXECUTE 'ALTER TYPE obj_name_tp ADD VALUE IF NOT EXISTS '||quote_ident($1)||';'
		USING l_table_name;


Или так:
EXECUTE 'ALTER TYPE obj_name_tp ADD VALUE IF NOT EXISTS quote_ident($1)'
		USING l_table_name;


Как все-таки выполнить такое выражение?
  • Вопрос задан
  • 678 просмотров
Решения вопроса 1
@romaro Автор вопроса
Работает:
DECLARE
    l_table_name	varchar(30) := lower(p_table_name);
BEGIN
	EXECUTE 'ALTER TYPE obj_name_tp ADD VALUE IF NOT EXISTS '||quote_literal(l_table_name);


Во-первых, не было никакого смысла передавать значение переменной в качестве плейсхолдера, т.к. EXECUTE находится в области видимости блока BEGIN, в котором эта переменная задекларирована.

Во-вторых, я пытался использовать функцию quote_ident(), которая оборачивает текст в двойные кавычки. Однако двойные кавычки (наряду с символами $$) используются для "прерывания" самого plpgsql-кода. Получалось, что я пытался вызвать ALTER TYPE без параметра, т.к. значение после EXISTS отсекалось.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы