It seems like when I
ALTER TABLE foo DISABLE TRIGGER ALL;
DELETE FROM foo;
The deletions don't get cascaded to other tables with
FOREIGN KEY ("fooId") REFERENCES "foo"("id") ON DELETE CASCADE
constraints, but I can't find anything in the documentation about this.
I also don't see any triggers I didn't create in
SELECT * FROM information_schema.triggers;
I'm guessing ON UPDATE/ON DELETE are implemented internally as triggers (which aren't visible in pgAdmin)? Does anyone know where this is documented?
Try here:
DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER
These forms configure the firing of trigger(s) belonging to the table. A disabled trigger is still known to the system, but is not executed when its triggering event occurs. For a deferred trigger, the enable status is checked when the event occurs, not when the trigger function is actually executed. One can disable or enable a single trigger specified by name, or all triggers on the table, or only user triggers (this option excludes internally generated constraint triggers such as those that are used to implement foreign key constraints or deferrable uniqueness and exclusion constraints). Disabling or enabling internally generated constraint triggers requires superuser privileges; it should be done with caution since of course the integrity of the constraint cannot be guaranteed if the triggers are not executed.
Related
I'd like just to confirm if the 'ALTER TABLE table_name DISABLE TRIGGER ALL' also disables DOMAIN checks in Postgres?
No, DOMAIN and CHECK constraints are not disabled.
Only some constraints are implemented as triggers in Postgres. The most notable would be a trigger on the "parent" table in the FK constraint, and triggers on deferrable unique / exclusion constraints. These require some complicated logic that cannot be checked against a single row and were, consequently, implemented as triggers.
DOMAIN checks are entirely "internal", the checks cannot use subqueries, and by all means operate like CHECK constraints. There should be no triggers.
You could check pg_trigger to see if your target table has any "internally defined' triggers.
What is the query to disable all constraints like foreign keys, primary keys but leave uniques?
PostgreSQL does not allow to disable constraints generally speaking. You can only disable foreign key constraints by disabling the related trigger used to implement the foreign keys.
See https://www.postgresql.org/docs/12/sql-altertable.html#SQL-ALTERTABLE-NOTES
DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER
One can disable or enable a single trigger specified by name, or all
triggers on the table, or only user triggers (this option excludes
internally generated constraint triggers such as those that are used
to implement foreign key constraints or deferrable uniqueness and
exclusion constraints). Disabling or enabling internally generated
constraint triggers requires superuser privileges; it should be done
with caution since of course the integrity of the constraint cannot be
guaranteed if the triggers are not executed.
I am learning Sequelize and models' foreign keys, however I don't understand what's the purpose deferable field
It will create a foreign key that will check the constraints
I don't understand what's constraints(limitations) here. should I define it? I already viewed the code on official docs but It's no help and can't understand its' usage. Would appreciate if someone help me understand.
The docs mention:
A collection of properties related to deferrable constraints. It can
be used to make foreign key constraints deferrable and to set the
constraints within a transaction. This is only supported in
PostgreSQL.
So, that's your hint to google for postgres foreign key deferrable or similar. The postgres docs say:
SET CONSTRAINTS sets the behavior of constraint checking within the
current transaction. IMMEDIATE constraints are checked at the end of
each statement. DEFERRED constraints are not checked until transaction
commit. Each constraint has its own IMMEDIATE or DEFERRED mode.
Upon creation, a constraint is given one of three characteristics:
DEFERRABLE INITIALLY DEFERRED, DEFERRABLE INITIALLY IMMEDIATE, or NOT
DEFERRABLE. The third class is always IMMEDIATE and is not affected by
the SET CONSTRAINTS command. The first two classes start every
transaction in the indicated mode, but their behavior can be changed
within a transaction by SET CONSTRAINTS.
Unpacking that: deferrable means you can "defer" the checking of foreign key constraints til the end of a transaction. (Transactions, by the way, are basically "groups of queries" that either all succeed, or, if one of them fails, all the others are rolled back too.)
Let's take a contrived example: imagine you have a blogs table that has a foreign key that points to a categories table. When you insert a new blog post, the category it links to must exist - otherwise that blogs to categories foreign key constraint will fail. BUT... if we use the deffered feature, then we could do something like this (in psuedo-code):
1. Being a transaction
2. Tell postgres to use deferred foreign key constraints for this transaction
3. Insert a blog that links to the "Hello World" category (which does not yet exist)
3a. (Note this is where Postgres would normally check the foreign key constraint and fail)
4. Insert the "Hello World" Category
5. Commit the transaction
6. Because we're using the DEFERRED feature, the foreign key check
will happen now, at the end of the transaction, instead of at 3a,
and it will succeed, because "Hello Wolrd" category now exists!
To cut a long story short, you should leave out the deferrable key (or set it to false) unless you know you need it.
I'm new to database triggers and I'm stuck with this:
Suppose that I have two different relations, R1 and R2, for which I specify two "independent" triggers. I mean, trigger TR1 for R1 and TR2 for R2. And suppose that both triggers are fired for the same event.
Which will be their execution order?
PostrgresSQL documentation states what happens for triggers defined on the same relation. But it's not clear about triggers defined on different relations, yet fired by the same event. I wonder if, in such situation, triggers are fired in a random order.
36.1. Overview of Trigger Behavior: If more than one trigger is defined for the same event on the same relation, the triggers will be fired in alphabetical order by trigger name. In the case of before triggers, the possibly-modified row returned by each trigger becomes the input to the next trigger. If any before trigger returns NULL, the operation is abandoned for that row and subsequent triggers are not fired.
... suppose that both triggers are fired for the same event.
This can only happen in 2 cases (in PostgreSQL):
With referential integrity constraint(s) (such as foreign keys)
Cascade/recursive trigger firing
Referential integrity constraints
These type of constraints will create a trigger to ensure referential integrity. In case of foreign keys, the (automatically) created trigger will have names like RI_ConstraintTrigger... SQLFiddle. The same rule applies to them (they will be fired in alphabetical order by trigger name amongst other triggers) except in one case: they can be deferred (globally, or initially deferred per constraints). Which means that they will be executed only at the end of the current transaction (or when SET CONSTRAINTS changes the mode of a constraint from DEFERRED to IMMEDIATE).
You can also create custom constraint triggers with CREATE CONSTRAINT TRIGGER ..., which will behave the same.
Cascade/recursive trigger firing
This is explicitly mentioned on the docs:
If a trigger function executes SQL commands then these commands might fire triggers again. This is known as cascading triggers. There is no direct limitation on the number of cascade levels. It is possible for cascades to cause a recursive invocation of the same trigger; for example, an INSERT trigger might execute a command that inserts an additional row into the same table, causing the INSERT trigger to be fired again. It is the trigger programmer's responsibility to avoid infinite recursion in such scenarios.
Their order are pretty straightforward, f.ex:
If UPDATE on R1 will trigger TR1 that UPDATEs R2, which will trigger TR2 (and both BEFORE triggers):
1) BEFORE triggers of R1 (f.ex. TR1)
1.1) BEFORE triggers of R2 (f.ex. TR2)
1.2) INSTEAD OF triggers of R2 (or do the actual operation)
1.3) AFTER triggers of R2
2) INSTEAD OF triggers of R1 (or do the actual operation)
3) AFTER triggers of R1
You could think, there is one more: what about inheritance?
Inheried tables not just doesn't inherit triggers, they won't fire their ancestors' triggers neither.
SQLFiddle
From http://dev.mysql.com/doc/refman/5.6/en/innodb-restrictions.html
Currently, cascaded foreign key actions do not activate triggers.
Does this work in MariaDB?
According to the documentation, it seems that it doesn't work in MariaDB either:
The following restrictions apply to triggers.
[...]
Triggers are not activated by foreign key actions.
"Foreign key actions" refers to the action to perform (RESTRICT, CASCADE, SET NULL, NO ACTION, SET DEFAULT) on the rows in the current table which references deleted or updated rows in the referenced table.
Also see related bugs:
MySQL: https://bugs.mysql.com/bug.php?id=11472
MariaDB: https://jira.mariadb.org/browse/MDEV-19402