Як часто буде спрацьовувати тригер ЗА ВСЯКОГО ЗАЯВЛЕННЯ, якщо операція викликана обмеженням FK з ОНОВЛЕННЯМИ КАСКАДАМ?


11

Я розумію, що тригер на таблиці t, визначений з, FOR EACH STATEMENTбуде працювати один раз, коли я виконую UPDATE t ....

Тепер, коли tце визначено з FOREIGN KEY ... REFERENCES a ... ON UPDATE CASCADE, і я оновлюю N рядків a, чи призведе до виклику тригера один раз чи N разів?

Інакше кажучи, чи зміни таблиці, каскадної обмеженням FK, більше схожі на одиницю UPDATE, або більше схожу на серію UPDATEs?


4
Ви можете створити тестовий випадок! Вставте в іншу таблицю тіла курок і подивіться, скільки рядків ви отримаєте. Потім напишіть це у власній відповіді на це питання (це дозволено, навіть рекомендується)!
Colin 't Hart

2
Головне згадування речення FOR EACH STATEMENTє ортогональним для решти питань. Обмеження ФК реалізуються за допомогою спеціальних тригерів FOR EACH ROW.
Ервін Брандстеттер

1
@Erwin "ЗА ВСЕ РЯДО" або "ЗА ВСЕ РЯДО Т"?
ypercubeᵀᴹ

@ypercube: я додав відповідь із деталями.
Ервін Брандстеттер

Відповіді:


6

Наразі закордонні ключові обмеження реалізуються за допомогою спеціальних внутрішніх механізмів. Усі вони запущені FOR EACH ROW.

Зауважте, що це деталі реалізації, які можуть змінюватися, тому не покладайтеся на них. Але основи не змінилися за останні пару основних версій, тому серйозні зміни навряд чи.

Я провів швидкий тест із простим обмеженням ФК від tblдо tbltype. Простий FK реалізований з чотирма простими внутрішніми тригерами FOR EACH ROWв моєму тесті на сторінці 9.4.
Ось короткий пробіг про те, як розслідувати:

SELECT oid  -- 74791
FROM   pg_constraint
WHERE  conrelid = 'tbl'::regclass
AND    contype = 'f';

SELECT objid, classid::regclass  -- 74792,74793,74794,74795 / 'pg_trigger'
FROM   pg_depend
WHERE  refobjid = 74791
AND   deptype = 'i'

SELECT tgrelid::regclass, tgname, tgfoid, tgtype FROM pg_trigger
WHERE  oid IN (74792,74793,74794,74795) ORDER BY tgfoid;

'tbl'    ;'RI_ConstraintTrigger_c_74794';1644;5
'tbl'    ;'RI_ConstraintTrigger_c_74795';1645;17
'tbltype';'RI_ConstraintTrigger_a_74792';1654;9
'tbltype';'RI_ConstraintTrigger_a_74793';1655;17

SELECT oid, proname FROM pg_proc
WHERE oid IN (1654,1655,1644,1645);

1644;'RI_FKey_check_ins'
1645;'RI_FKey_check_upd'
1654;'RI_FKey_noaction_del'
1655;'RI_FKey_noaction_upd'

Два внутрішніх "бездіяльності" спрацьовує tbltype.
Увімкнено два внутрішні тригери "перевірки" tbl.
Усі вони запускаються FOR EACH ROW, як зазначено непарними номерами в tgtype.

2 байти Postgres tgtype smallintпредставляють int16вихідний код С, де кодується найменш значущий біт TRIGGER_TYPE_ROW. Детальне пояснення тут:

Ви можете легко протестувати це за допомогою пари однакових тригерів, де ви лише змінюєте FOR ROW/ STATEMENT...


5

Це виконується N разів, і найпростіший спосіб це побачити - це виконати операцію з попередньою EXPLAIN ANALYZEформою, тобто

EXPLAIN ANALYZE UPDATE a SET col = 1 WHERE othercol = 'foo';

Це дасть вам подібну інформацію:

Trigger for constraint t_col_fk on a: time=1.300 calls=9

(тестовано з 9.2)


1
Це мене дещо дивує. Тестували на 9.4 з тими ж результатами.
дезсо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.