powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Как использовать динамические имена колонок
7 сообщений из 7, страница 1 из 1
Как использовать динамические имена колонок
    #34572089
Oleg Zhovtanyuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вопрос по сабжу.

Есть триггер, ведущий лог удаленных записей:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
CREATE OR REPLACE FUNCTION rep_delete_stamp() RETURNS trigger 
AS $$
DECLARE 
	pkns name[] := NULL;
	pkn name := NULL;
	pkv VARCHAR( 34 ) := NULL;
BEGIN
	pkns := rep_pkeys(TG_RELNAME);
	IF (array_upper(pkns,  1 ) =  1 ) THEN
		pkn := pkns[ 1 ];
		EXECUTE 'pkv = OLD.' || pkn; -- Ошибка!
                -- pkv := OLD.PK_COL_NAME; -- А так - работает.
	ELSE
		-- TODO: Compound key values.
	END IF;
	INSERT INTO rep_deletelog (tablename, pkname, pkvalue) 
	VALUES 	(TG_RELNAME, pkn, pkv);
	RETURN NULL;
END;
$$ LANGUAGE plpgsql;

Лог - в отдельной таблице:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE rep_deletelog (
	uid SERIAL NOT NULL,
	tablename name NOT NULL,
	pkname name NULL,
	pkvalue VARCHAR( 34 ) NULL,
	ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
	PRIMARY KEY (uid)
);

Для каждой операции удаления берется имя таблицы (из TG_RELNAME), ее первичный ключ (имена колонок "на лету" вынимаются из pg_catalog функцией rep_pkeys(name)) и нужно еще взять значение ключа. Так вот взять его из NEW никак не получается. Ни селектом, ни как в коде приведено. Ошибку бросает. Как бороться?
...
Рейтинг: 0 / 0
Как использовать динамические имена колонок
    #34572210
assa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oleg ZhovtanyukТак вот взять его из NEW никак не получается. Ни селектом, ни как в коде приведено. Ошибку бросает. Как бороться?как правило вам в plpgsql такое невозможно, рекомендуют другие языки -
http://sql.ru/forum/actualsearch.aspx?search=NEW+EXECUTE&sin=0&a=&ma=0&bid=7&dt=-1&s=1&so=1
но вот я нарвался на старое решение-прокладку (вставка строки NEW/OLD в темповую таблу, котораю потом пихается в EXECUTE) - посмотрите. вдруг - работает? чем черт не шутит.
http://sql.ru/forum/actualthread.aspx?tid=253810&pg=1&hl=new+execute+%e8%ec%ff

хотя это и извращение, имхо.
...
Рейтинг: 0 / 0
Как использовать динамические имена колонок
    #34572345
assa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
assa но вот я нарвался на старое решение-прокладку (вставка строки NEW/OLD в темповую таблу, котораю потом пихается в EXECUTE) - посмотрите. вдруг - работает? чем черт не шутит.
http://sql.ru/forum/actualthread.aspx?tid=253810&pg=1&hl=new+execute+%e8%ec%ff?

хотя это и извращение, имхо.кстати освежил - сработало. Токмо ommited FROM в 8.1. пришлось подправить.:
Код: plaintext
	query := 'insert into ' ||TG_RELNAME|| '_audit select ' || quote_literal('u') ||',  now(), user, *  FROM old_temp;';
...
Рейтинг: 0 / 0
Как использовать динамические имена колонок
    #34572542
Serik Akhmetov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Совсем недавно было решение на pl/Perl.
...
Рейтинг: 0 / 0
Как использовать динамические имена колонок
    #34573187
assa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Serik AkhmetovСовсем недавно было решение на pl/Perl.дык я потому и в поиск полез. (в разрезе - припоминая о). И ба! - наткнулся на возможность таки передать нью-олд в Execute в plpgsql, о которой уже и подзабыл (намедни, читая искомое, пытался воспроизвести - не получилось, а тут само нашлось).
...
Рейтинг: 0 / 0
Как использовать динамические имена колонок
    #34573884
Kruchinin Pahan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
assa assa но вот я нарвался на старое решение-прокладку (вставка строки NEW/OLD в темповую таблу, котораю потом пихается в EXECUTE) - посмотрите. вдруг - работает? чем черт не шутит.
http://sql.ru/forum/actualthread.aspx?tid=253810&pg=1&hl=new+execute+%e8%ec%ff?

хотя это и извращение, имхо.кстати освежил - сработало. Токмо ommited FROM в 8.1. пришлось подправить.:
Код: plaintext
	query := 'insert into ' ||TG_RELNAME|| '_audit select ' || quote_literal('u') ||',  now(), user, *  FROM old_temp;';

Проверил, в 8.1 работает. А в 8.2 не компилит, ругается на конструкцию SELECT OLD.* INTO ;-|
Никто не в курсе, что нужно в 8.2 подправить?
...
Рейтинг: 0 / 0
Как использовать динамические имена колонок
    #34574146
Oleg Zhovtanyuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо за помощь всем отозвавшимся.

Решение, предложенное assa, и у меня сработало. На всякий случай (вдруг кто еще в поиск за этим полезет) привожу рабочий код триггера.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
CREATE OR REPLACE FUNCTION rep_delete_stamp() RETURNS trigger 
AS $$
DECLARE 
	pkn name := NULL;
	pkv VARCHAR( 34 ) := NULL;
	pkns name[] := NULL;
	query text;
BEGIN
	pkns := rep_pkeys(TG_RELNAME);
	IF (array_upper(pkns,  1 ) =  1 ) THEN
		pkn := pkns[ 1 ];
		pkns := NULL;
		SELECT OLD.* INTO TEMPORARY rep_tmp;
		query := 'INSERT INTO rep_deletelog (tablename, pkname, pkvalue) SELECT ''' || TG_RELNAME || ''', ''' || pkn || ''', ' || pkn || ' FROM rep_tmp;';
		EXECUTE query;
		DROP TABLE rep_tmp;
	ELSE
		-- TODO: Implement compound primary key support, as necessary.
		RAISE EXCEPTION 'The table % has compound primary key - not supported', TG_RELNAME;
	END IF;
	RETURN NULL;
END;
$$ LANGUAGE plpgsql;

Но. Производительность DELETE-а при этом упала "ниже плинтуса", так что пришлось переделывать алгоритм: оставил в логе удаленных записей только имя таблицы и timestamp, - так полегчало.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Как использовать динамические имена колонок
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]