powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / работа с типом record
11 сообщений из 11, страница 1 из 1
работа с типом record
    #33643559
Kisian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
в некоторой функции:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
...
Declare rec record;

begin 
   select * into rec from <Таблица>;

   for indx in  1  .. <Количество полей в Rec> 
      loop
        if rec<Индекс поля> <Некое условие> then <Некое действие>....
.....

Вопрос:
Есть ли возможность в PL/PGSQL получить информацию о количестве полей в типе record и возможность обращения к полю в типе record по его индексу?

В документации найти конкретного ответа не могу.
...
Рейтинг: 0 / 0
работа с типом record
    #33644344
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pgplsql'е скорее всего никак (ни количество ни по нидексу).

а ващето при запросе select * from
обращаются к полям по индексу тока сумашедшие...

а за такое надо вообще убивать:

select * from a1
union
select * from a2
...
Рейтинг: 0 / 0
работа с типом record
    #33644430
Kisian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
wbearpgplsql'е скорее всего никак (ни количество ни по нидексу).

а ващето при запросе select * from
обращаются к полям по индексу тока сумашедшие...

а за такое надо вообще убивать:

select * from a1
union
select * from a2

Моя проблема не верно Вами понята. Хотя и саму проблему я не писал.
А нужно мне это для следующего.
У меня есть некая таблица, скажем журнал для отслеживания изменений данный в полях других таблиц, структуры:
Имя таблицы,
Имя поля,
Значение поля.

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

Или подскажете решение по реализации ЕДИНОГО журнала изменений? А нужен именно ЕДИНЫЙ журнал.
...
Рейтинг: 0 / 0
работа с типом record
    #33644460
Фотография Александр Гoлдун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kisian пишет:

> Или подскажете решение по реализации ЕДИНОГО журнала изменений? А нужен
> именно ЕДИНЫЙ журнал.

Зачем дублировать содержимое журнала транзакций?
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
работа с типом record
    #33644566
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Kisian
тада забей на plpgsql и пиши на сях..там это реально и немного быстрее.

SPI_fname(TupleDesc rowdesc, int colnumber);
и т.п.

2Александр Гoлдун
человек репликацию видимо пишет...не мешай :)
...
Рейтинг: 0 / 0
работа с типом record
    #33645337
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну зачем сразу C. plpythonu с поставленной задачей прекрасно справится. (Может только в скорости уступит, но я не думаю, что он будет журналить биллинговую таблицу)
...
Рейтинг: 0 / 0
работа с типом record
    #33645774
Kisian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Александр Гoлдун
Kisian пишет:

> Или подскажете решение по реализации ЕДИНОГО журнала изменений? А нужен
> именно ЕДИНЫЙ журнал.

Зачем дублировать содержимое журнала транзакций?
Posted via ActualForum NNTP Server 1.3


Я в этом деле начинающий. Подскажите как добраться до журнала транзакций?

автор wbear
тада забей на plpgsql и пиши на сях..там это реально и немного быстрее.

SPI_fname(TupleDesc rowdesc, int colnumber);
и т.п.


Вы советуете все же отказаться от использования PLPGSQL при написании логики на сервере и использовать более мощные по функциональности языки?
...
Рейтинг: 0 / 0
работа с типом record
    #33645941
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Я в этом деле начинающий. Подскажите как добраться до журнала транзакций?

он лежит в папке x_log(вроде) с инстансом посгреса ...но не думаю что ты от туда сможешь достать, то что тебе надо.

Александр Гoлдун подумал что ты хочешь реализовать в посгресе свой персональный механизм транзакций..поэтому и спросил: "зачем если он уже есть?".

>Вы советуете все же отказаться от использования PLPGSQL при написании логики на сервере и использовать более мощные по функциональности языки?

это даже не совет... это решение этой задачи (видимо единственное).
вам надо взять другой язык для написания ЭТОЙ хранимой процедуры(тригера) например Си или как посоветовал Funny_Falcon plpython.. они позволяют решить эту задачу(определять название колонок из селекта). a в PL/PGSQL нет этой возможности.
...
Рейтинг: 0 / 0
работа с типом record
    #33646557
-me-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Гы, а если примерно так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
begin;
create table change_log (
  change_id    bigint not null default nextval('change_log_seq') primary key,
  table_name   text not null,
  key_value    text not null,
  change_date  timestamptz not null default now()
);

create table change_log_what_changed(
  change_id    bigint not null references change_log on delete cascade,
  column_name  text,
  old_value    text,
  new_value    text,
  primary key  (change_id, column_name)
);

create or replace function create_new_change_log_record( _table_name text, _key_value text) returns bigint as $$
declare _new_change_id bigint;
begin
  _new_change_id := nextval('change_log_seq');
  insert into change_log (change_id, table_name, key_value) values (_new_change_id , _table_name, _key_value);
  return _new_change_id;
end $$ language 'plpgsql';

create or replace function generate_change_log_trigger_proc(_TABLENAME text, _KEYNAME text) returns text as $$
DECLARE
  _proc_text text;
  _rec record;
BEGIN
_proc_text := 'CREATE OR REPLACE FUNCTION track_changes_on_' || _TABLENAME || ' () RETURNS TRIGGER AS $aproc$
DECLARE _chg_id BIGINT;
BEGIN
  _chg_id := create_new_change_log_record( ' || quote_literal(_TABLENAME) || ', text(NEW.' || _KEYNAME || ') );' ;
  FOR _rec IN SELECT attname FROM pg_attribute
                             JOIN pg_class c ON (attrelid = c.oid)
                             WHERE relname = _TABLENAME  AND NOT attisdropped AND attnum >=  0 
              LOOP
  _proc_text := _proc_text || '\nIF NEW.' || _rec.attname || ' <> OLD.' || _rec.attname || ' THEN
    INSERT INTO change_log_what_changed (change_id, column_name, old_value, new_value)
      VALUES ( _chg_id,' || quote_literal(_rec.attname) || ',  OLD.' || _rec.attname ||', NEW.'|| _rec.attname || '); END IF;';
  END LOOP;
  _proc_text := _proc_text || '   RETURN NEW; END $aproc$ language plpgsql; ';
  return  _proc_text;
END$$ language 'plpgsql';

CREATE OR REPLACE FUNCTION start_change_log ( _TABLENAME text, _KEYNAME text) returns void as $$
BEGIN
  EXECUTE generate_change_log_trigger_proc( _TABLENAME, _KEYNAME);
  EXECUTE 'CREATE TRIGGER ' || _TABLENAME ||  '_chg_log_trg AFTER UPDATE ' ||
              ' ON ' || _TABLENAME || ' FOR EACH ROW EXECUTE PROCEDURE track_changes_on_' || _TABLENAME || '()';
  RETURN;
END$$ LANGUAGE 'plpgsql';

CREATE OR REPLACE FUNCTION stop_change_log ( _TABLENAME text, _KEYNAME text) returns void as $$
BEGIN
  EXECUTE 'DROP TRIGGER ' || _TABLENAME ||  '_chg_log_trg ON  ' || _TABLENAME ;
  RETURN;
END$$ LANGUAGE 'plpgsql';

create table t_c_l (id serial, data text, I_data int, f_data float);
insert into t_c_l values ( 1 , 'test 1',  0 , - 1 );
insert into t_c_l values ( 2 , 'test 2',  1 ,  2 );

select  generate_change_log_trigger_proc( 't_c_l', 'id')    ;
select start_change_log('t_c_l', 'id');

update t_c_l set data = 'test 1.1' , f_data =  1 . 5  where id =  1 ;
update t_c_l set data = 'test 2.1' , i_data =  3  where id =  2 ;

select * from change_log join change_log_what_changed using (change_id) order by change_id desc;

update t_c_l set data = 'test 3';

select * from change_log join change_log_what_changed using (change_id) order by change_id desc;
rollback;
Запускаем:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
BEGIN
CREATE SEQUENCE
CREATE TABLE
CREATE TABLE
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE TABLE
INSERT  74130691   1 
INSERT  74130692   1 
                                                                                       generate_change_log_trigger_proc    
----------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------
 CREATE OR REPLACE FUNCTION track_changes_on_t_c_l () RETURNS TRIGGER AS $aproc$
DECLARE _chg_id BIGINT;
BEGIN
  _chg_id := create_new_change_log_record( 't_c_l', text(NEW.id) );
IF NEW.id <> OLD.id THEN
    INSERT INTO change_log_what_changed (change_id, column_name, old_value, new_value)
      VALUES ( _chg_id,'id',  OLD.id, NEW.id); END IF;
IF NEW.data <> OLD.data THEN
    INSERT INTO change_log_what_changed (change_id, column_name, old_value, new_value)
      VALUES ( _chg_id,'data',  OLD.data, NEW.data); END IF;
IF NEW.i_data <> OLD.i_data THEN
    INSERT INTO change_log_what_changed (change_id, column_name, old_value, new_value)
      VALUES ( _chg_id,'i_data',  OLD.i_data, NEW.i_data); END IF;
IF NEW.f_data <> OLD.f_data THEN
    INSERT INTO change_log_what_changed (change_id, column_name, old_value, new_value)
      VALUES ( _chg_id,'f_data',  OLD.f_data, NEW.f_data); END IF;   RETURN NEW; END $aproc$ language plpgsql;
( 1  запись)

 start_change_log
------------------

( 1  запись)

UPDATE  1 
UPDATE  1 
 change_id | table_name | key_value |           change_date           | column_name | old_value | new_value
-----------+------------+-----------+---------------------------------+-------------+-----------+-----------
          2  | t_c_l      |  2          |  05 . 04 . 2006   14 : 17 : 09 . 981291  EEST | data        | test  2     | test  2 . 1 
          2  | t_c_l      |  2          |  05 . 04 . 2006   14 : 17 : 09 . 981291  EEST | i_data      |  1          |  3 
          1  | t_c_l      |  1          |  05 . 04 . 2006   14 : 17 : 09 . 981291  EEST | data        | test  1     | test  1 . 1 
          1  | t_c_l      |  1          |  05 . 04 . 2006   14 : 17 : 09 . 981291  EEST | f_data      | - 1         |  1 . 5 
(записей:  4 )

UPDATE  2 
 change_id | table_name | key_value |           change_date           | column_name | old_value | new_value
-----------+------------+-----------+---------------------------------+-------------+-----------+-----------
          4  | t_c_l      |  2          |  05 . 04 . 2006   14 : 17 : 09 . 981291  EEST | data        | test  2 . 1   | test  3 
          3  | t_c_l      |  1          |  05 . 04 . 2006   14 : 17 : 09 . 981291  EEST | data        | test  1 . 1   | test  3 
          2  | t_c_l      |  2          |  05 . 04 . 2006   14 : 17 : 09 . 981291  EEST | data        | test  2     | test  2 . 1 
          2  | t_c_l      |  2          |  05 . 04 . 2006   14 : 17 : 09 . 981291  EEST | i_data      |  1          |  3 
          1  | t_c_l      |  1          |  05 . 04 . 2006   14 : 17 : 09 . 981291  EEST | data        | test  1     | test  1 . 1 
          1  | t_c_l      |  1          |  05 . 04 . 2006   14 : 17 : 09 . 981291  EEST | f_data      | - 1         |  1 . 5 
(записей:  6 )

ROLLBACK

Т.е. триггеры-то можно генерировать динамически :)

P.S. Пример чисто ущербно-познавательный :)
...
Рейтинг: 0 / 0
работа с типом record
    #33646567
-me-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
извиняюсь за многа букв '-'
...
Рейтинг: 0 / 0
работа с типом record
    #33646661
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
:) да вам батенька энергию девать некуда ...

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


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