61阅读

外键约束-外键约束 举例

发布时间:2018-01-05 所属栏目:我和我妈的那些事14

一 : 外键约束 举例

(1)基本介绍

外键作用: 使两张表形成关联,外键只能引用外表中的指定列的值!

建立外键的前提: 本表的列必须与外键类型相同(外键必须是外表的主键)。

指定外键关键字: foreign key(列名)

引用外键关键字: references <外键表名>(外键列名)

事件触发限制: on delete和on update , 可设参数cascade(跟随外键改动), restrict(限制外表中的外键改动),set Null(设空值),set Default(设默认值),[默认]no action

例如:

outTable表 主键 id 类型 int

创建含有外键的表:

create table temp(

id int,

name char(20),

foreign key(id) references outTable(id) on delete cascade on update cascade);

说明:把id列 设为外键 参照外表outTable的id列 当外键的值删除 本表中对应的列筛除当外键的值改变本表中对应的列值改变。

(2)定义数据表

假如某个电脑生产商,它的数据库中保存着整机——http://www.61k.com——和配件的产品信息。用来保存整机产品信息的表叫做 pc;用来保存配件供货信息的表叫做 parts。

Pc表

在 pc 表中有一个字段,用来描述这款电脑所使用的CPU型号;

在 parts 表中相应有一个字段,描述的正是CPU的型号,我们可以把它想成是全部CPU的型号列表。

很显然,这个厂家生产的电脑,其使用的 cpu 一定是供货信息表(parts)中存在的型号。这时,两个表中就存在一种约束关系(constraint)—— pc 表中的 cpu 型号受到 parts 表中型号的约束。

首先我们来创建 parts 表:

Create TABLE parts (

... 字段定义 ...,

model VARCHAR(20) NOT NULL,

... 字段定义 ...

);

接下来是 pc 表:

Create TABLE pc (

... 字段定义 ...,

cpumodel VARCHAR(20) NOT NULL,

... 字段定义 ...

};

(3)设置索引

若要设置外键,在参照表 (referencing table,即pc表) 和被参照表 (referenced table,即parts表) 中,相对应的两个字段必须都设置索引 (index),也可以设置为候选键(key),因为在很多情况下索引(index)和候选键(key)的功能等同。

对parts表:

Alter TABLE parts ADD INDEX idx_model (model);

这句话的意思是,为 parts 表增加一个索引,索引建立在 model 字段上,给这个索引起个名字叫idx_model。

对pc表也类似:

Alter TABLE pc ADD INDEX idx_cpumodel (cpumodel);

事实上这两个索引可以在创建表的时候就设置。这里只是为了突出其必要性。

(4)定义外键

下面为两张表之间建立前面所述的那种“约束”。因为pc的CPU型号必须参照parts表中的相应型号,所以我们将pc表的cpumodel字段设置为“外键”(FOREIGN KEY),即这个键的参照值来自于其他表。

Alter TABLE pc ADD CONSTRAINT fk_cpu_model

FOREIGN KEY (cpumodel)

REFERENCES parts(model);

第一行是说要为pc表设置外键,给这个外键起一个名字叫做fk_cpu_model;第二行是说将本表的cpumodel字段设置为外键;第三行是说这个外键受到的约束来自于parts表的model字段。

这样,我们的外键就搞好了!如果我们试着Create一台pc,它所使用的 cpu 的型号是 parts 表中不存在的,那么 MySQL 会禁止这台 PC 被 Create 出来。

(5)级联操作

一切看起来都挺好的,不是吗?

考虑以下这种情况:

技术人员发现,一个月之前输入到 parts 表中的某个系列的 cpu (可能有[www.61k.com很多款)的型号全都输错了一个字母,现在需要改正。我们希望的是,当 parts 表中那些 Referenced Column 有所变化时,相应表中的 Referencing Column 也能自动更正。

可以在定义外键的时候,在最后加入这样的关键字:

ON Update CASCADE; 即在主表更新时,子表(们)产生连锁更新动作,似乎有些人喜欢把这个叫“级联”操作。:)

如果把这语句完整的写出来,就是:

Alter TABLE pc ADD CONSTRAINT fk_cpu_model

FOREIGN KEY (cpumodel)

REFERENCES parts(model)

ON Update CASCADE;

除了 CASCADE 外,还有 RESTRICT(禁止主表变更)、SET NULL(子表相应字段设置为空)等操作

二 : SQLSEVER中的那些键和约束

SQL Server中有五种约束类型,分别是 PRIMARY KEY约束、FOREIGN KEY约束、UNIQUE约束、DEFAULT约束、和CHECK约束。查看或者创建约束都要使用到 Microsoft SQL Server Managment Studio。

1. PRIMARY KEY约束

在表中常有一列或多列的组合,其值能唯一标识表中的每一行。这样的一列或多列成为表的主键(Primary Key)。一个表只能有一个主键,而且主键约束中的列不能为空值。

查看PRIMARY KEY约束可以在object explorer中依次展开Databases &ndash;> 选择你要查看的数据库(在我的例子中是chargesystem) &ndash;> 表 &ndash;> 你要查看的表(在我的例子中是BasicTale)-> 列

sql sever SQLSEVER中的那些键和约束

如上图所示,Primary Key 有一把金色的小钥匙。ModifyIDea 即为BasicTable表的primary key。

创建PRIMARY KEY约束可以右键点击表,然后选择设计,打开表设计器,选中行,点击上面的金色小钥匙,来创建Primary Key。

sql sever SQLSEVER中的那些键和约束

也可以右键点击想设为主键的行,然后选择设置主键。

2. FOREIGN KEY约束

外键(Foreign Key)是用于建立和加强两个表(主表与从表)的一列或多列数据之间的连接的。创建约束的顺序是先定义主表的主键,再对从表定义外键约束。

查看FOREIGN KEY约束,展开列,可以看到灰色的小钥匙为Foreign Key;展开Keys,可以看到Foreign Key约束的名字为FK_contact_company。

sql sever SQLSEVER中的那些键和约束

在表设计器中,也可以点击上面的关系按钮,这样就可以查看到所有的Foreign Key约束

sql sever SQLSEVER中的那些键和约束

sql sever SQLSEVER中的那些键和约束

sql sever SQLSEVER中的那些键和约束

上面的例子可以看到billTable 表的OperatorID为外键,OperatorIDea 表的OperatorIDea为主键。

下面来演示一下如何创建的该Foreign Key约束。

同样是点击完关系按钮之后,在弹出的对话框中选择添加

sql sever SQLSEVER中的那些键和约束

然后点击下面的红色框内的按钮:

sql sever SQLSEVER中的那些键和约束

按下图中那样设置主表、主键和从表、外键

sql sever SQLSEVER中的那些键和约束

然后点击 OK,不要忘记保存你的设计。

sql sever SQLSEVER中的那些键和约束

3. UNIQUE约束(唯一键或索引)

UNIQUE约束用于确保表中的两个数据行在非主键中没有相同的列值。与PRIMARY KEY约束类似,UNIQUE约束也强制唯一性,但UNIQUE约束用于非主键的一列或多列组合,且一个表可以定义多个UNIQUE约束,另外UNIQUE约束可以用于定义多列组合。

还以BillTable为例,假设我们要约束BillIDea为唯一的,点击管理索引和键

sql sever SQLSEVER中的那些键和约束

然后点击Add来添加Unique约束

sql sever SQLSEVER中的那些键和约束

选择列为BillID(ASC), 是唯一的为是。

sql sever SQLSEVER中的那些键和约束

关闭并保存你的设计,这样一个Unique约束就创建好了。

扩展:sqlsever 主键自增 / sql sever取主键名 / sql 外键约束

三 : 玩转MySQL中的外键约束之PHP篇

一、利用外键约束更新MySQL中的数据

现在,最流行的开源关系型数据库管理系统非MySQL莫属,而MySQL又支持多个存储引擎,其中默认的也是速度较快的存储引擎为MyISAM,对许多读者来说,在开发自己数据库驱动的web应用程序之前,可能已经使用了它很长一段时间了。

然而,有时候我们的项目可能需要额外的特性,例如需要处理外键约束,这时我们就需要用到其它类型的MySQL存储引擎。在这种情况下,InnoDB表将非常适合我们的要求,尽管在性能方面可能比MyISAM表要稍逊一筹。大家知道,使用InnoDB表外键约束主要优点之一就是,它使我们可以在数据库级别处理和维护多个表之间的关系,而无需将此任务推给与这些表打交道的应用程序的某些模块或者程序库。

当然,前面的几篇文章中,我们已经就IndoDB表的外键约束做过相应介绍,但是那里都是通过手工方式来操作外键约束的。在本文中,我们将说明如何在更新和删除父表中的数据时,如何通过脚本语言来触发相应子表的级联更新和删除操作。

这里,我们博客应用程序的数据层由两个表构成,在前面的示例中,对这些表的操作,都是通过手工键入SQL命令完成的,现在,我们将介绍如何使用PHP程序设计语言来完成这些工作。之所以选择PHP,是因为它目前MySQL最常见的搭配语言,下面我们以PHP 5为例来说明如何外键约束操作两个InnoDB表。 通过阅读本文,您将更加真切地体会到外键约束的特性。

现在,我们开始见证PHP 5和外键约束结合在一起所带来的威力吧!

二、以级联方式更新和删除数据库中的数据

古人云,温故而知新,那么先让我们来回顾一下前面学过的内容吧。之前,我们介绍过如何运用外键约束级联更新和删除存放博客文章评论的InnoDB表中的数据。如果您尚未阅读前面的文章也不要紧,下面我们简单回顾这些内容。

这里是我们的示例中用到的两个表的定义,如下所示:


DROP TABLE IF EXISTS `test`.`blogs`;
CREATE TABLE `test`.`blogs` (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`title` TEXT,
`content` TEXT,
`author` VARCHAR(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `test`.`comments`;
CREATE TABLE `test`.`comments` (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`blog_id` INT(10) UNSIGNED DEFAULT NULL,
`comment` TEXT,
`author` VARCHAR(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `blog_ind` (`blog_id`),
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`blog_id`) REFERENCES `blogs` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

上面的代码定义了两个表,需要注意一下第二个,因为它为“blog_id”字段规定了一个约束,所以当post表中的数据被更新和删除时,将触发相应的级联操作。

为了帮您理解这一过程,我们可以在表中填上一些数据,这时可以通过SQL语句INSERT来完成,如下:


INSERT INTO blogs (id, title, content, author) VALUES (NULL,'Title of the first blog entry', 'Content of the first blog entry', 'IAN')

INSERT INTO comments (id, blog_id, comment, author) VALUES (NULL, 1, 'Commenting first blog entry', 'Tom'), (NULL, 1, 'Commenting first blog entry', 'Rose')

现在,我们唯一的一条博客数据已经有了两条评论数据,如果由于任何原因需要更新博客及其评论数据的话,可以通过下列命令完成:


UPDATE blogs SET id = 2, title = 'Title of the first blog entry', content = 'Content of the first blog entry', author = 'John Doe' WHERE id = 1

这看起来非常简单,但是,如果我说将博客数据连同相应的评论数据一同删除会更加简单,您能会相信吗?如果不信的话,请看下面的SQL语句:

DELETE FROM blogs WHERE id = 2

如您所见,这就是删除指定博客及其评论所需的全部SQL代码,这足以证明通过外键约束维护两个InnoDB表的完整性到底有多么的方便。

迄今为止,我们已经简单回顾之前所学的内容,接下来,我们将继续探索这些表的约束的各种优点。 就像本文开头部分介绍的那样,我们将开始讲解如何通过PHP 5内置的MySQL抽象类来生成对我们的示例表的级联更新。

三、利用PHP 5以级联方式更新数据库

好了,现在开始详细介绍如何使用流行的服务器端脚本语言PHP 5来以级联方式更新我们的示例表。为此,我们需要编写允许我们访问上面定义的InnoDB表的代码,就本例而言,我们使用PHP 5的MySQL抽象类来达此目的。下面给出具体的代码:


class MySQL
{
private $result = NULL;
private $link = NULL;

//连接到MySQL

public function __construct($host, $user, $password, $database)
{
if (FALSE === ($this->link = mysqli_connect($host, $user, $password, $database)))
{
throw new Exception('Error : ' . mysqli_connect_error());
}
}

//执行查询

public function query($query)
{
if (is_string($query) AND empty($query) === FALSE)
{
if (FALSE === ($this->result = mysqli_query($this->link, $query)))
{
throw new Exception('Error performing query ' . $query . ' Error message :' .mysqli_error($this->link));
}
}
}

//从结果集返回数据

public function fetch()
{
if (FALSE === ($row = mysqli_fetch_object($this->result)))
{
mysqli_free_result($this->result);
return FALSE;
}
return $row;
}

//获取插入ID

public function getInsertID()
{
return mysqli_insert_id($this->link);
}

//结果集中的行数

public function countRows()
{
if ($this->result !== NULL)
{
return mysqli_num_rows($this->result);
}
}

//关闭数据库连接

function __destruct()
{
mysqli_close($this->link);
}
}

如上所示,上面定义的MySQL抽象类十分简单,它提供了许多常用的方法,用于执行查询、统计结果集行数以及获取插入ID。需要格外注意的是,这个类内部使用了PHP扩展mysqli来跟MySQL打交道,所以整体看来是很容易理解的。

好了,我们已经定义了一个可以用于跟MySQL数据库相交互的PHP 5类,现在我们要做的就是利用它的API对前面定义的InnoDB表执行级联更新。

四、MySQL抽象类

现在,为了演示如何使用上述的MySQL类级联更新前文中的数据表,我们需要重新定义那两个表,以便使其只能执行这些更新的操作。这里是它们的定义,这两个表将作为我们的示例博客应用程序的数据层:


DROP TABLE IF EXISTS `test`.`blogs`;
CREATE TABLE `test`.`blogs` (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`title` TEXT,
`content` TEXT,
`author` VARCHAR(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `test`.`comments`;
CREATE TABLE `test`.`comments` (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`blog_id` INT(10) UNSIGNED DEFAULT NULL,
`comment` TEXT,
`author` VARCHAR(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `blog_ind` (`blog_id`),
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`blog_id`) REFERENCES `blogs` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

如上所述,通过给最后一个表中的blog_id字段规定外键约束,我们已经把两个表联系在了一起,接下来让我们使用前面定义的MySQL抽象类给它们填入必要的数据。

我们假设这个类被单独放入一个名为mysqlclass.php文件中,下面的脚本将向blog表中插入单篇博客文章,并向comments表中插入两则评论:


require_once 'mysqlclass.php';

$db = new MySQL('host', 'user', 'password', 'test');

//在blogs数据库表中插入新数据

$db->query("INSERT INTO blogs (id, title, content, author) VALUES (NULL,'Title of the first blog entry', 'Content of the first blog entry', 'IAN')");

$insid = $db->getInsertID();

//在comments数据库表中插入新评论

$db->query("INSERT INTO comments (id, blog_id, comment, author) VALUES (NULL, $insid, 'Commenting first blog entry', 'Tom'), (NULL, $insid, 'Commenting first blog entry', 'Rose')");

虽然我们的这个MySQL类能够抽象地访问数据库,但是相应的SQL查询还得手工编写。同时,它正好可以使我们可以展示每当第一个表中的数据更新时,如何使用该类来更新与第一个数据表相关的评论。

执行该级联更新操作的代码片断如下所示:


//更新blogs表中的数据(comments表中的有关数据将自动更新)

$db->query("UPDATE blogs SET id = 2, title = 'Title of the first blog entry', content = 'Content of the first blog entry', author = 'John Doe' WHERE id = 1");

尽管另外添加了一个与上述InnoDB表打交道的抽象类,但是触发级联更新所需的SQL代码仍然保持高度简洁。这说明,各表之间的关系的完整性仍然是在数据库级别进行维护的,而不是由PHP 5应用程序所维护的。

五、小结

到目前为止,我们详细讲解了如何通过PHP 5内置的抽象类使用外键约束来更新两个InnoDB表中的数据。 我们希望本文能够对您利用服务器端脚本使用外键约束时能够有所启发。在后面的文章中,我们将继续探讨外键约束有关的内容。

四 : MySQL外键约束创建及删除

创建外键定义 :

CREATE TABLE categories (

category_id tinyint(3) unsigned NOT NULL AUTO_INCREMENT,

name varchar(30) NOT NULL,

PRIMARY KEY(category_id)

) ENGINE=INNODB;

INSERT INTO categories VALUES (1, ‘SQL Server’), (2, ‘Oracle’), (3, ‘PostgreSQL’), (4, ‘MySQL’), (5, ‘SQLite’);

CREATE TABLE members (

member_id INT(11) UNSIGNED NOT NULL,

name VARCHAR(20) NOT NULL,

PRIMARY KEY(member_id)

) ENGINE=INNODB;

CREATE TABLE articles (

article_id INT(11) unsigned NOT NULL AUTO_INCREMENT,

title varchar(255) NOT NULL,

category_id tinyint(3) unsigned NOT NULL,

member_id int(11) unsigned NOT NULL,

INDEX (category_id),

FOREIGN KEY (category_id) REFERENCES categories (category_id),CONSTRAINT fk_member FOREIGN KEY (member_id) REFERENCES members (member_id),

PRIMARY KEY(article_id)

) ENGINE=INNODB;

categories.category_id和articles.category_id、members.member_id和articles.member_id已经建立外键关系,只有articles.category_id的值存在与categories.category_id表中并且articles.member_id的值存在与members.member_id表中才会允许被插入或修改。:

删除外键定义 :

定义外键的时候articles.member_id外键比articles.category_id子句多了一个CONSTRAINT fk_member。这个fk_member就是用来删除外键定义用的:

ALTER TABLE articles DROP FOREIGN KEY fk_member;

这样articles.member_id外键定义就被删除

如果定义时没有指定CONSTRAINT fk_symbol(即外键符号)时MySQL会自己创建一个,可以通过以下命令查看:

SHOW CREATE TABLE articles;

+———-+————————————+ | Table| Create Table| +———-+————————————+ | articles | CREATE TABLE `articles` ( `article_id` int(11) unsigned NOT NULL auto_increment, `category_id` tinyint(3) unsigned NOT NULL, `member_id` int(11) unsigned NOT NULL, `title` varchar(255) NOT NULL, PRIMARY KEY (`article_id`), KEY `category_id` (`category_id`), KEY `member_id` (`member_id`), CONSTRAINT `articles_ibfk_1` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1| +———-+————————————+ 1 row in set (0.01 sec)

可以看出articles.category_id的外键符号为articles_ibfk_1,因此就可以执行以下命令删除外键定义:

ALTER TABLE articles DROP FOREIGN KEY articles_ibfk_1;

五 : sql server删除外键约束

x先找出约束名字

然后删除它

我给个例子

--测试环境

--主表

create table test1(id int primary key not null,value int)

insert test1 select 1,2

go

--从表

create table test2(id int references test1(id),value int)

go

--第一步:找出test2表上的外键约束名字

--2000

exec sp_helpconstraint 'test2'

--可以在constr[www.61k.com]aint_name 属性中找到外键约束名字

--2005

select name

from sys.foreign_key_columns f join sys.objects o on f.constraint_object_id=o.object_id

where f.parent_object_id=object_id('test2')

/*

name

---------------------------------

FK__test2__id__08EA5793*/

--第二步:删除外键约束

alter table test2 drop constraint FK__test2__id__08EA5793

--第三步:检查表上是否还有外键约束

--只要使用第一步里面的查找语句即可

本文标题:外键约束-外键约束 举例
本文地址: http://www.61k.com/1118683.html

61阅读| 精彩专题| 最新文章| 热门文章| 苏ICP备13036349号-1