98 lines
3.7 KiB
Plaintext
98 lines
3.7 KiB
Plaintext
|
++++ Introduction
|
||
|
|
||
|
A foreign key constraint specifies that the values in a column (or a group of columns) must match the values appearing in some row of another table. In other words foreign key constraints maintain the referential integrity between two related tables.
|
||
|
|
||
|
Say you have the product table with the following definition:
|
||
|
|
||
|
<code type='php'>
|
||
|
class Product extends Doctrine_Record
|
||
|
{
|
||
|
public function setTableDefinition()
|
||
|
{
|
||
|
$this->hasColumn('id', 'integer', null, 'primary');
|
||
|
$this->hasColumn('name', 'string');
|
||
|
$this->hasColumn('price', 'decimal', 18);
|
||
|
}
|
||
|
}
|
||
|
</code>
|
||
|
|
||
|
Let's also assume you have a table storing orders of those products. We want to ensure that the order table only contains orders of products that actually exist. So we define a foreign key constraint in the orders table that references the products table:
|
||
|
|
||
|
<code type='php'>
|
||
|
class Order extends Doctrine_Record
|
||
|
{
|
||
|
public function setTableDefinition()
|
||
|
{
|
||
|
$this->hasColumn('order_id', 'integer', null, 'primary');
|
||
|
$this->hasColumn('product_id', 'integer');
|
||
|
$this->hasColumn('quantity', 'integer');
|
||
|
}
|
||
|
public function setUp()
|
||
|
{
|
||
|
$this->hasOne('Product', 'Order.product_id');
|
||
|
|
||
|
// foreign key columns should *always* have indexes
|
||
|
|
||
|
$this->index('product_id', array('fields' => 'product_id'));
|
||
|
}
|
||
|
}
|
||
|
</code>
|
||
|
|
||
|
When exported the class {{Order}} would execute the following SQL:
|
||
|
|
||
|
<code type="sql">
|
||
|
CREATE TABLE orders (
|
||
|
order_id integer PRIMARY KEY,
|
||
|
product_id integer REFERENCES products (id),
|
||
|
quantity integer,
|
||
|
INDEX product_id_idx (product_id)
|
||
|
)
|
||
|
</code>
|
||
|
|
||
|
Now it is impossible to create orders with product_no entries that do not appear in the products table.
|
||
|
|
||
|
We say that in this situation the orders table is the referencing table and the products table is the referenced table. Similarly, there are referencing and referenced columns.
|
||
|
|
||
|
|
||
|
++++ Constraint actions
|
||
|
|
||
|
//CASCADE//:
|
||
|
Delete or update the row from the parent table and automatically delete or update the matching rows in the child table. Both ON DELETE CASCADE and ON UPDATE CASCADE are supported. Between two tables, you should not define several ON UPDATE CASCADE clauses that act on the same column in the parent table or in the child table.
|
||
|
|
||
|
//SET NULL// :
|
||
|
Delete or update the row from the parent table and set the foreign key column or columns in the child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier specified. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported.
|
||
|
|
||
|
//NO ACTION// :
|
||
|
In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary key value is not allowed to proceed if there is a related foreign key value in the referenced table.
|
||
|
|
||
|
//RESTRICT// :
|
||
|
Rejects the delete or update operation for the parent table. NO ACTION and RESTRICT are the same as omitting the ON DELETE or ON UPDATE clause.
|
||
|
|
||
|
//SET DEFAULT// :
|
||
|
|
||
|
In the following example we define two classes, User and Phonenumber with their relation being one-to-many. We also add a foreign key constraint with onDelete cascade action.
|
||
|
|
||
|
<code type='php'>
|
||
|
class User extends Doctrine_Record
|
||
|
{
|
||
|
public function setUp()
|
||
|
{
|
||
|
$this->hasMany('Phonenumber', 'Phonenumber.user_id', array('onDelete' => 'cascade'));
|
||
|
}
|
||
|
public function setTableDefinition()
|
||
|
{
|
||
|
$this->hasColumn('name', 'string', 50);
|
||
|
$this->hasColumn('loginname', 'string', 20);
|
||
|
$this->hasColumn('password', 'string', 16);
|
||
|
}
|
||
|
}
|
||
|
class Phonenumber extends Doctrine_Record
|
||
|
{
|
||
|
public function setTableDefinition()
|
||
|
{
|
||
|
$this->hasColumn('phonenumber', 'string', 50);
|
||
|
$this->hasColumn('user_id', 'integer');
|
||
|
}
|
||
|
}
|
||
|
</code>
|