Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Вопрос по триггеру / 16 сообщений из 16, страница 1 из 1
08.06.2007, 20:49
    #34585208
Крупский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
Внутри ТФ на апдейт таблички формирую строки InsertRow и InsertedRow для динамического запроса , скажем InsertRow := ''name,...mydate'' , InsertedRow := ''OLD.name,...,NOW()'' соответственно. Триггера(правила) на INSERT нема.

...
InsertCmd := ''INSERT INTO ''
|| quote_ident(TG_TABLE_NAME)
|| '' (''
|| InsertRow
|| '') VALUES (''
|| InsertedRow
|| ''); '';

EXECUTE InsertCmd ;
...

В результате внесения измения возникает ошибка внутри ТФ, типа :

ERROR: OLD used in query that is not a rule.
КОНТЕКСТ SQL statement ''INSERT INTO my_table (name,...,mydate) VALUES (OLD.name,...,NOW()); ''

Теперь вопрос: Как с ентим забороца?
С уважением
...
Рейтинг: 0 / 0
09.06.2007, 10:26
    #34585645
assa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
...
Рейтинг: 0 / 0
09.06.2007, 21:59
    #34586891
Крупский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
предложено в примере и вставить строку в ТФ:

...
SELECT OLD.* Into temporary old_temp;
...

То в моём форточном ПГ 8.2.3 имею:

ERROR: syntax error at "temporary"
SQL state: 42601
Detail: Expected record variable, row variable, or list of scalar variables following INTO.
Context: compile of PL/pgSQL function "proc_historical_update" near line 19


Не останавливаюсь... Пробую так:

SELECT * INTO TEMPORARY old_temp FROM OLD;

Имею на выходе тоже:

ERROR: syntax error at "TEMPORARY"
SQL state: 42601
Detail: Expected record variable, row variable, or list of scalar variables following INTO.
Context: compile of PL/pgSQL function "proc_historical_update" near line 20


Тогда тупо, для проверки... пишу в отдельном окне:

SELECT * INTO TEMPORARY temp_country FROM t_town;
select * from temp_country;

И как не странно всё работает!!!.. Типа, ура!

Обрадованно вставляю данный селект в ТФ... Результат ясен?... Таже ошибка!!! (((

Вопчем нуна помосчь... Иначе придёца для каждой таблицы писать триггер на историю ((( шо не есть гут.
С уважением
...
Рейтинг: 0 / 0
13.06.2007, 05:56
    #34590488
Kruchinin Pahan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
Крупский
То в моём форточном ПГ 8.2.3 имею:

+1
Не форточный, но 8.2.3.
В 8.1.х работало, в 8.2.х перестало. В чем проблема, пока не разобрался.
...
Рейтинг: 0 / 0
13.06.2007, 16:47
    #34592485
assa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
Kruchinin Pahan Крупский
То в моём форточном ПГ 8.2.3 имею:

+1
Не форточный, но 8.2.3.
В 8.1.х работало, в 8.2.х перестало. В чем проблема, пока не разобрался.скорее всего с 8.2 отпала возможность вставки ROW в таблицу (INSERT ROW.* INTO table). Возможно - из-за отключения т.н. "опущенного FROM" в поведении 8.2. "по умолчанию". Т.ч. видимо и этот (последний) финт ушами уже не работает. Т.ч. выход, видимо, - пользовать другие языки (окромя plpgsql), как и утверждает большинство предложений в поиске.

ps 8.2 пока не мучал. т.ч. все - скорее на уровне предположения.
...
Рейтинг: 0 / 0
14.06.2007, 14:46
    #34594853
Крупский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
по идёт тока plpgsql :(... Какой язык посоветуете для форточек, и как его подключить.. Просто, как и многие здесь присутсвующие, нахожусь в лимите времени для выбора. Надеюсь на коллективный опыт. Заранее багодарен за ответ.
С уважением
...
Рейтинг: 0 / 0
14.06.2007, 16:10
    #34595195
Serik Akhmetov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
КрупскийВнутри ТФ на апдейт таблички формирую строки InsertRow и InsertedRow для динамического запроса , скажем InsertRow := ''name,...mydate'' , InsertedRow := ''OLD.name,...,NOW()'' соответственно. Триггера(правила) на INSERT нема.Не очень понял, что вы хотите, при изменении таблицы делать в триггере вставку в эту же таблицу ? Это легко сделать на plperl. Обсуждалось не давно, ищите.
...
Рейтинг: 0 / 0
14.06.2007, 16:21
    #34595249
Крупский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
мона вести аль в отдельной "исторической таблице"(или в лог-файле) аль записывать в саму себя(ессно создавая дополнительные колонки)... Я выбрал второй вариант - это первое, ответ на вопрос "ЗАЧЕМ?". Второе и главное... Вы советуете использовать plperl но меня в большей степени интетесует ГДЕ его найти(скачать) и как его подключить к форточному ПГ 8.2.+??? Ведь в поставке идёт тока plpsql...
С уважением
ЗЫ если уже был Явный ответ на мой вопрос... решение на плперл... Я бы был признателен на пряму ссылку.
...
Рейтинг: 0 / 0
14.06.2007, 17:05
    #34595442
assa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
Крупскийпо идёт тока plpgsql 1. перечитав ваш пост про непроходимость TEMPORARY смекнул, что проблема может быть именно в этом слове, (т.е. если действительно в 8.2. пропала возможность строить темповые таблы в контексте ХП, без использования Execute)
Попробуйте вместо SELECT INTO выполнить
Код: plaintext
INSERT INTO  _постоянная_таблица SELECT * FROM OLD;
(понятно, для произвольных таблиц такой триггер не сработает, но чисто для проверки)



2. хотя кажется в вашем случае все могло бы быть несколько проще - если
а. вы действительно знаете (вычисляете) список архивируемых полей OLD, и
б. все нужные поля кастятся в text (имеется адекватный способ откастить как туда так и обратно), то измените контекст на что-то вроде :
Код: plaintext
query:='INSERT INTO my_table (name,...,mydate) VALUES ('||COALESCE(OLD.name,'NULL')||','||...'||',NOW());';


3. если же вы имеете однотипные (для простоты) пк (а луше - одноименные для всех таблиц - чтобы не вычислять поля пк в триггере) - то можно обойтись несколько иначе. Вместо перечисления VALUES вставьте
'INSERT INTO ... SELECT * FROM ... WHERE пк ='|| OLD.пк ||';'
(если архив в той же таблице - на BEFORE INSERT повесте триггерное беспощадное наваривание пк - тогда вставка пк всегда будет по счетчику, что бы вы не пытались в пк впихнуть). В итоге вы сможете "архивировать" даже поля, не поддающиеся легкому преобразованию в текст и обратно.
...
Рейтинг: 0 / 0
14.06.2007, 21:49
    #34596082
Крупский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
"общего триггера" ессно:
1. я написал его для конкретной таблицы и всё прокатило... :) "ОЛД" работает как положено...
2. Триггер общий.. посему если в таблице вдруг окажеца блоб-поле то COALESCE вроде как не к месту...
3. Над этим пунктом подумаю...

Привожу примерный текст триггера, который у меня получился.. может так будет лучше дать совет чё и как может кому поможет 8)...

Код: 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.
CREATE OR REPLACE FUNCTION proc_historical_update()  RETURNS trigger AS'

DECLARE
  i     integer;
  vDim  integer;
  vcol_names  varchar [] = ''{}'' ;
  InsertRow   text = '''';
  InsertedRow text = '''';
  InsertCmd   text  = '''';
 
BEGIN
-- Если мы изменяем видимость записи, то выходим и историю не пишем!
    IF NEW.Deleted <> OLD.Deleted THEN                    

-- Сюда вставлять изменение в подчиненных таблицах! Если это трабует алгоритм... Подумать над этим позже
--      UPDATE t_town SET t_town.Deleted = NEW.Deleted WHERE t_town.idCountry = OLD.idKey;

       RETURN NEW;
    END IF;

-- Запись истории в таблицу!

    vcol_names := proc_table_name_array(quote_ident(TG_TABLE_NAME)); -- получим имена всех столбцов таблицы

-- Формируем строку для INSERT  переменной InsertCmd

    i := 2 ; -- не трогаем колонку первичного ключа idKey! Он у нас всегда первый в списке столбцофф
    vDim := array_upper(vcol_names,1); -- Узнаем размерность массивчика
    WHILE  i <= vDim 
    LOOP 
        IF quote_ident(vcol_names[i]) = ''idactualkey'' THEN   
                  InsertedRow := InsertedRow || ''OLD.Idkey''; 
        ELSEIF vcol_names[i] = ''dateend'' THEN   
                       InsertedRow := InsertedRow || ''NOW()'';        
        ELSE 
             InsertedRow := InsertedRow || ''OLD.'' || vcol_names[i]; 
        END IF;

        InsertRow := InsertRow || vcol_names[i];
-- Запятую ставим тока если не последний операнд
        IF i<vDim THEN
           InsertRow   := InsertRow   || '', '';
           InsertedRow := InsertedRow || '', '';
        END IF; 
        i := i + 1;       
    END LOOP;

    InsertCmd := ''INSERT INTO '' 
              || TG_TABLE_NAME
              || '' ('' 
              || InsertRow
              || '') VALUES (''
              || InsertedRow
              || ''); '';

    EXECUTE InsertCmd ; 
          
    NEW.DateBegin := NOW();     
   
RETURN  NEW;

END;
' LANGUAGE 'plpgsql';


C уважением
...
Рейтинг: 0 / 0
15.06.2007, 09:22
    #34596519
Serik Akhmetov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
Установка plperl:
- скачать ActivePerl, установить его
- прописать в путях
- стандартно создать язык CREATE LANGUAGE

plperl и перебор полей обсуждался здесь
триггер обсуждался здесь , я форумы перепутал :)

сделать цикл по хешмассиву $_TD->{old} можно примерно так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
    %old_rec = $_TD->{old};
    foreach $var (sort(keys(%old_rec))) 
    {
     $val = $old_rec{$var};
#     ${var} # имя поля
#     ${val} # значение
    }
...
Рейтинг: 0 / 0
15.06.2007, 10:52
    #34596796
assa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
Крупский"общего триггера" ессно:
ОФТОП: безотносительно того, что вы выберете в кач-ве решения, я как то смотрел на задачу ведения лога в той же таблице, что и сами записи. Из некоторых вполне понятных соображений, решил, что ведение признака активности записи в другой таблице, с короткой записью, более рационально для версионника. Т.е. схема такая:
1. запись в "основной" таблице никогда не обновляется. и никогда (пользователем) не удаляется.
2. ведется два "ключевых" поля в основной таблице. Одно - безальтернативный триггерный счетчик. Реальный пк. Второе - дефолтный счетчик - "эффективный п.к." (множественные вхождения). На реальный пк смотрит табличка составленная из реальных пк и активных эффективных ключей. В ней уже оба поля - уникальные индексированные. Отсутствие в ней ключа основной таблицы записи означает, что эта версия записи не активна. Отсутствие же в ней записи с "эффективным ключом" - что запись "удалена". Все внешние связи из других таблиц осуществляются на поле-эффективный ключ таблицы ключей. (реально таблица подменяется вью из связи этих 2-х таблиц). Понятно, что экономя на записях версий, мы теряем в скорости на джойнах. Но я использовал такую схему для ведения массовой, многократно повторяющейся выгрузки данных из внешнего приложения. Когда промеж выгрузок записи могут меняться во внешнем приложении. (в триггере на вставку проверялось совпадение записей, в случае которого запись отменялась, в случае различия - вставлялась, а запись в таблице ключей обновлялась). Выгрузку делал поначалу на триггерах. Правда не заметил существенной разницы со случаем ведения всех полей в одной таблице (но уже с выгрузкой непосредственно процедурами), но, честно признаюсь, и особо не мерял.

ЗЫ. а насчет универсальности триггера - имхо не стоит выделки. лучше написать автомат, генерящий требуемую вариацию скрипта триггера конкретно под таблицу - быстрее в итоге будет работать.
...
Рейтинг: 0 / 0
15.06.2007, 11:30
    #34596961
Крупский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
"исторического триггера"... всё ап чём Вы пишете ессно всё пральна, но я остановился на том варианте, что привёл выше... По ходу смысл тот же в использовании ОЛД/НЬЮ как в варианте дополнительной "исторической таблицей", так и в записи историю прям в текущую таблицу... Что там, что там.. при использовании ОЛД/НЬЮ для формирования строки под EXECUTE, возникнет таже проблема... Я не понимаю почему убрали возможность в ТФ юзать временные таблички... И почему документация не соответствует реалиям!!! :(
Что касаемо плперл я попробую установить, хотя это уже усложняет систему в целом... и буду надеяца, что хункция spi_exec_query лишена недостаткофф и работает с ОЛД/НЬЮ без проблем...
С уважением
...
Рейтинг: 0 / 0
19.06.2007, 21:28
    #34606200
Крупский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
Попытался поставить ПЛПЕРЛ ... Сходу не удалось.. Пишет, мол, АшЫПка:

could not load library "c:/.../PostgreSQL/8.2/lib/plperl.dll": unknown error 126

Сдаёца мне, что какая-то проблема со слэшами...в мастдайке... Кто-ньть ставил доп язык в творении Уильяма Гейтса.. для постгре...?? Поделитесь плз.. Или сцылочкой по установке ;)...
С уважением

ЗЫ Накатил новую версию 8.2.4 Таже проблема с Execute и OLD ((
...
Рейтинг: 0 / 0
20.06.2007, 00:17
    #34606334
Крупский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
Глянул... В plperl.dll требует наличия нужной(зависимой) длл-ки perl58.dll.. Скачал и установил 5.8.ххх ЭктивПерл... в постгресовую lib\ переписал на всякий случай енту длл.... Эффект тотже (
С уважением
...
Рейтинг: 0 / 0
29.06.2007, 10:48
    #34628044
Remach
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос по триггеру
assa Крупскийпо идёт тока plpgsql
...
3. если же вы имеете однотипные (для простоты) пк (а луше - одноименные для всех таблиц - чтобы не вычислять поля пк в триггере) - то можно обойтись несколько иначе. Вместо перечисления VALUES вставьте
'INSERT INTO ... SELECT * FROM ... WHERE пк ='|| OLD.пк ||';'
(если архив в той же таблице - на BEFORE INSERT повесте триггерное беспощадное наваривание пк - тогда вставка пк всегда будет по счетчику, что бы вы не пытались в пк впихнуть). В итоге вы сможете "архивировать" даже поля, не поддающиеся легкому преобразованию в текст и обратно.

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


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