-<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.30 2004/08/08 21:33:11 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.31 2004/10/21 21:33:59 tgl Exp $ -->
<chapter id="ddl">
<title>Data Definition</title>
<para>
Restricting and cascading deletes are the two most common options.
- <literal>RESTRICT</literal> can also be written as <literal>NO
- ACTION</literal> and it's also the default if you do not specify
- anything. There are two other options for what should happen with
- the foreign key columns when a primary key is deleted:
+ <literal>RESTRICT</literal> prevents a statement from deleting a
+ referenced row. <literal>NO ACTION</literal> means that if any
+ referencing rows still exist when the constraint is checked, an error
+ is raised; this is the default if you do not specify anything.
+ (The essential difference between these choices is that
+ <literal>NO ACTION</literal> allows the check to be deferred until
+ later in the transaction, whereas <literal>RESTRICT</literal> does not.)
+ There are two other options:
<literal>SET NULL</literal> and <literal>SET DEFAULT</literal>.
+ These cause the referencing columns to be set to nulls or default
+ values, respectively, when the referenced row is deleted.
Note that these do not excuse you from observing any constraints.
For example, if an action specifies <literal>SET DEFAULT</literal>
but the default value would not satisfy the foreign key, the
<para>
Finally, we should mention that a foreign key must reference
- columns that are either a primary key or form a unique constraint.
+ columns that either are a primary key or form a unique constraint.
If the foreign key references a unique constraint, there are some
additional possibilities regarding how null values are matched.
These are explained in the reference documentation for
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.84 2004/08/02 04:25:31 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.85 2004/10/21 21:33:59 tgl Exp $
PostgreSQL documentation
-->
<listitem>
<para>
- Theses clauses specify a foreign key constraint, which specifies
+ These clauses specify a foreign key constraint, which requires
that a group of one or more columns of the new table must only
- contain values which match against values in the referenced
- column(s) <replaceable class="parameter">refcolumn</replaceable>
- of the referenced table <replaceable
- class="parameter">reftable</replaceable>. If <replaceable
+ contain values that match values in the referenced
+ column(s) of some row of the referenced table. If <replaceable
class="parameter">refcolumn</replaceable> is omitted, the
primary key of the <replaceable
class="parameter">reftable</replaceable> is used. The
</para>
<para>
- A value inserted into these columns is matched against the
+ A value inserted into the referencing column(s) is matched against the
values of the referenced table and referenced columns using the
given match type. There are three match types: <literal>MATCH
FULL</>, <literal>MATCH PARTIAL</>, and <literal>MATCH
clause specifies the action to perform when a referenced column
in the referenced table is being updated to a new value. If the
row is updated, but the referenced column is not actually
- changed, no action is done. There are the following possible
+ changed, no action is done. Referential actions apart from the
+ check of <literal>NO ACTION</literal> can not be deferred even if
+ the constraint is deferrable. There are the following possible
actions for each clause:
<variablelist>
<listitem>
<para>
Produce an error indicating that the deletion or update
- would create a foreign key constraint violation. This is
- the default action.
+ would create a foreign key constraint violation.
+ If the constraint is deferred, this
+ error will be produced at constraint check time if there still
+ exist any referencing rows. This is the default action.
</para>
</listitem>
</varlistentry>
<term><literal>RESTRICT</literal></term>
<listitem>
<para>
- Same as <literal>NO ACTION</literal> except that this action
- will not be deferred even if the rest of the constraint is
- deferrable and deferred.
+ Produce an error indicating that the deletion or update
+ would create a foreign key constraint violation.
+ This is the same as <literal>NO ACTION</literal> except that
+ the check is not deferrable.
</para>
</listitem>
</varlistentry>
<term><literal>SET NULL</literal></term>
<listitem>
<para>
- Set the referencing column values to null.
+ Set the referencing column(s) to null.
</para>
</listitem>
</varlistentry>
<term><literal>SET DEFAULT</literal></term>
<listitem>
<para>
- Set the referencing column values to their default value.
+ Set the referencing column(s) to their default values.
</para>
</listitem>
</varlistentry>
</para>
<para>
- If primary key column is updated frequently, it may be wise to
- add an index to the foreign key column so that <literal>NO
- ACTION</literal> and <literal>CASCADE</literal> actions
- associated with the foreign key column can be more efficiently
- performed.
+ If the referenced column(s) are changed frequently, it may be wise to
+ add an index to the foreign key column so that referential actions
+ associated with the foreign key column can be performed more
+ efficiently.
</para>
</listitem>
</varlistentry>
<programlisting>
CREATE TABLE cinemas (
- id serial,
- name text,
- location text
+ id serial,
+ name text,
+ location text
) TABLESPACE diskvol1;
</programlisting>
</para>
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.135 2004/10/16 21:16:36 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.136 2004/10/21 21:33:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
fk_trigger->actions[1] = '\0';
fk_trigger->isconstraint = true;
- fk_trigger->deferrable = fkconstraint->deferrable;
- fk_trigger->initdeferred = fkconstraint->initdeferred;
fk_trigger->constrrel = myRel;
switch (fkconstraint->fk_del_action)
{
case FKCONSTR_ACTION_NOACTION:
+ fk_trigger->deferrable = fkconstraint->deferrable;
+ fk_trigger->initdeferred = fkconstraint->initdeferred;
fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_del");
break;
case FKCONSTR_ACTION_RESTRICT:
fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_del");
break;
case FKCONSTR_ACTION_CASCADE:
+ fk_trigger->deferrable = false;
+ fk_trigger->initdeferred = false;
fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_del");
break;
case FKCONSTR_ACTION_SETNULL:
+ fk_trigger->deferrable = false;
+ fk_trigger->initdeferred = false;
fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_del");
break;
case FKCONSTR_ACTION_SETDEFAULT:
+ fk_trigger->deferrable = false;
+ fk_trigger->initdeferred = false;
fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_del");
break;
default:
fk_trigger->actions[0] = 'u';
fk_trigger->actions[1] = '\0';
fk_trigger->isconstraint = true;
- fk_trigger->deferrable = fkconstraint->deferrable;
- fk_trigger->initdeferred = fkconstraint->initdeferred;
fk_trigger->constrrel = myRel;
switch (fkconstraint->fk_upd_action)
{
case FKCONSTR_ACTION_NOACTION:
+ fk_trigger->deferrable = fkconstraint->deferrable;
+ fk_trigger->initdeferred = fkconstraint->initdeferred;
fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_upd");
break;
case FKCONSTR_ACTION_RESTRICT:
fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_upd");
break;
case FKCONSTR_ACTION_CASCADE:
+ fk_trigger->deferrable = false;
+ fk_trigger->initdeferred = false;
fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_upd");
break;
case FKCONSTR_ACTION_SETNULL:
+ fk_trigger->deferrable = false;
+ fk_trigger->initdeferred = false;
fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_upd");
break;
case FKCONSTR_ACTION_SETDEFAULT:
+ fk_trigger->deferrable = false;
+ fk_trigger->initdeferred = false;
fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_upd");
break;
default:
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.172 2004/09/10 18:39:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.173 2004/10/21 21:33:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* If we found some, check that they fit the deferrability
- * but skip ON <event> RESTRICT ones, since they are
+ * but skip referential action ones, since they are
* silently never deferrable.
*/
if (pg_trigger->tgfoid != F_RI_FKEY_RESTRICT_UPD &&
- pg_trigger->tgfoid != F_RI_FKEY_RESTRICT_DEL)
+ pg_trigger->tgfoid != F_RI_FKEY_RESTRICT_DEL &&
+ pg_trigger->tgfoid != F_RI_FKEY_CASCADE_UPD &&
+ pg_trigger->tgfoid != F_RI_FKEY_CASCADE_DEL &&
+ pg_trigger->tgfoid != F_RI_FKEY_SETNULL_UPD &&
+ pg_trigger->tgfoid != F_RI_FKEY_SETNULL_DEL &&
+ pg_trigger->tgfoid != F_RI_FKEY_SETDEFAULT_UPD &&
+ pg_trigger->tgfoid != F_RI_FKEY_SETDEFAULT_DEL)
{
if (stmt->deferred && !pg_trigger->tgdeferrable)
ereport(ERROR,