Можно ли динамически петлю через столбцы таблицы?

StackOverflow https://stackoverflow.com/questions/3083749

Вопрос

У меня есть триггерная функция для теста настольный, который имеет следующий фрагмент кода:

IF TG_OP='UPDATE' THEN
    IF OLD.locked > 0 AND
 (       OLD.org_id <> NEW.org_id OR
            OLD.document_code <> NEW.document_code OR
            -- other columns ...
 )
THEN
    RAISE EXCEPTION 'Message';
-- more code

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

Как это можно сделать?

Это было полезно?

Решение

Взгляните на информацию information_schema, есть вид «столбцы». Выполните запрос, чтобы получить все текущие столбцы из таблицы, который выпустил триггер:

SELECT 
    column_name 
FROM 
    information_schema.columns 
WHERE 
    table_schema = TG_TABLE_SCHEMA 
AND 
    table_name = TG_TABLE_NAME;

Петля через результат и там вы идете!

Больше информации можно найти в Точное руководство.

Другие советы

От 9,0 beta2 документации о WHEN Пункт в триггерах, которые могут быть в состоянии использовать в более ранних версиях в телу триггера:

OLD.* IS DISTINCT FROM NEW.*

или, возможно, (от 8.2 заметок выпуска)

IF row(new.*) IS DISTINCT FROM row(old.*)

Используйте PL / Perl или PL / Python. Они намного лучше подходят для таких задач. много лучше.

Вы также можете установить HSTORE-NEW, И используйте его семантику Row-> HStore, но это определенно не хорошая идея при использовании нормальных данных.

В Postgres 9.0 или позже добавить WHEN пункт к вашему определению триггера (CREATE TRIGGER утверждение):

CREATE TRIGGER foo
BEFORE UPDATE
FOR EACH ROW
WHEN (OLD IS DISTINCT FROM NEW)  -- parentheses required!
EXECUTE PROCEDURE ...;

Только возможен только для триггеров BEFORE / AFTER UPDATE, где оба OLD и NEW определены. Вы бы получили исключение, пытаясь использовать это WHEN оговорка INSERT или DELETE триггеры.

И радикально упростить триггер функция соответственно:

...
IF OLD.locked > 0 THEN
   RAISE EXCEPTION 'Message';
END IF;
...

Нет необходимости проверять IF TG_OP='UPDATE' ... Так как этот триггер работает только для UPDATE так или иначе.

Или переместите это состояние в пункте, когда тоже:

CREATE TRIGGER foo
BEFORE UPDATE
FOR EACH ROW
WHEN (OLD.locked > 0
  AND OLD IS DISTINCT FROM NEW)
EXECUTE PROCEDURE ...;

Оставив только безусловный RAISE EXCEPTION В вашей функции триггера, которая называется только при запуске с.

Прочитайте тонкую печать:

В BEFORE триггер, то WHEN условие оценивается непосредственно перед выполнением функции или будет выполнена, поэтому используя WHEN не существенно отличается от тестирования того же состояния в начале функции триггера. Обратите внимание, что NEW Строка, наблюдаемая условием, является текущее значение, возможно, модифицировано более ранние триггеры. Также BEFORE триггер WHEN условие не разрешено изучить системные колонны NEW строка (например, как oid), потому что те не будут установлены.

В ан AFTER триггер, то WHEN Состояние оценивается сразу после возникновения обновления строки, и он определяет, очевидно ли событие, чтобы выстрелить спусковой крючок в конце оператора. Так что когда Ан AFTER триггер WHEN Состояние не возвращает true, нет необходимости в очереди события, ни для повторной обработки строки в конце оператора. Это может привести к значительным ускорению в заявлениях, которые изменяют много строк, если триггер требуется только для нескольких строк.

Связанный:

Также решить вопрос о вопросе

Можно ли динамически петлю через столбцы таблицы?

Да. Примеры:

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top