1:類型
約束的類型一共分三種
域約束: 涉及一個或多個列,(限制某一列的數據大于0)
實體約束: 相同的值不能存在于其他的行中
引用完整性約束: 一個表中的一個列與某個表中的另一個列的值匹配
2:命名
約束是可以命名的 一般這樣命名:
pk_customer_***
pk代表主鍵 customer代表主鍵所在的表后面是你自己定義的(要確保整個名稱的唯一性)
3:主鍵約束
主鍵約束:一般就是id, 一個表中最多有一個主鍵
例子1
use accounting
create table employee
(
id int identity not null,
firstname varchar(20) not null
)
例子2
use accounting
alter table employee
add constraint pk_employeeid
primary key (id)
4:外鍵約束
外鍵約束用在確保數據完整性和兩個表之間的關系上
先看例子
create table orders
(
id int identity not null primary key,
customerid int not null foreign key references customer(id),
orderdate smalldatetime not null,
eid int not null
)
注意:這個表的外鍵必須是另一個表的主鍵!
在現有表上添加外鍵
alter table orders
add constraint fk_employee_creator_order
foreign key (eid) references employee(employeeid)
使用表自引用
表內至少要有一行數據才可以這么做
alter table employee
add constraint fk_employee_has_manager
foreign key (managerid) references employee(employeeid)
創建表的時候做表自引用 就可以忽略 foreign key 語句
表自引用的外鍵列 必須允許為null 要不是不允許插入的(避免對最初行的需要)
一個表與另一個表有約束,這個表是不能被刪除的
級聯操作
先看例子
create table orderdetails
(
orderid int not null ,
id int not null ,
description varchar(123) not null,
--設置主鍵
constraint pkOrderdetails primary key (orderid,id),
--設置外鍵,級聯操作
constraint fkOrderContainsDetails
foreign key (orderid)
references orders(orderid)
on update no action
on delete cacade
)
on delete cacade 當刪除父記錄時 同時刪除該記錄
也就是當刪除orders表中的一條記錄,
與之相關的orderdetails表中的記錄也將被刪除
級聯的深度是沒有限制的,但是每個外鍵都必須設置on delete cacade
no action是可選的
5:unique約束
unique約束與主鍵約束類似,同樣也是要求指定的列有唯一的值
但是一個表中可以有多個unique約束的列,同時這個列允許存在null值。(最多有一個null值)
看例子:
create table shippers
(
id int indentity not null primery key,
zip varchar(10) not null ,
phoneno varchar(14) not null unique
)
例子二:
alter table employee
add constraint ak_employeeSSN
unique(ssn)
6:check約束
check不局限于一個特定的列,可以約束一個列,也可以通過某個列來約束另一個列
定義check約束使用的規則與where子句中的基本一樣
下面我寫幾個
between 1 and 12
like '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
in ('ups','fed ex','usps')
price >=0
shipdate >= orderdate
看例子:
alter table customers
add constraint cn_customerDateinsystem
check
(dateinsystem <= getdate())
getdate()函數得到當前時間,上面這個例子的意思是dateinsystem列的數據不能大于當前時間
現在如果給這個列插入一個明天的時間,就會出錯
7:default約束
如果插入的新行在定義了默認值的列上沒有給出值,那么這個列上的數據就是定義的默認值
默認值只在insert語句中使用
如果插入的記錄給出了這個列的值,那么該列的數據就是插入的數據
如果沒有給出值,那么該列的數據總是默認值
8:禁用約束
在創建約束之前,數據庫中已經有一些不符合規矩的數據存在。
創建約束之后,又想加入一些不符合規矩的數據。
這些時候就要禁用約束。primary key 和 unique約束 這對孿生約束是不能禁用的
對一個已經存在數據的表加一個約束:
alter table customers
add constraint cn_customerPhoneNo
check
(phone like '([0-9][0-9][0-9])[0-9][0-9][0-9][0-9][0-9][0-9]')
如果表內有不符合這個約束的記錄,sqlserver就會報錯
如果這樣寫,就不會報錯了
alter table customers
with no check
add constraint cn_customerPhoneNo
check
(phone like '([0-9][0-9][0-9])[0-9][0-9][0-9][0-9][0-9][0-9]')
如果需要把一些不符合規矩的數據加入到表中怎么辦
這時候就需要臨時禁用現有的約束:
alter table customers
nocheck
constraint cn_customerPhoneNo
--允許不帶套插入,此處的名稱是前面定義的
insert into customer (phone) values (123456)
--開始不帶套插入!
alter table customers
check
constraint cn_customerPhoneNo
--下次插入要帶套
?
9. FOREIGN KEY約束標識表之間的關系。
一個表的外鍵指向另一個表的候選鍵。當外鍵值沒有候選鍵時,外鍵可防止操作保留帶外鍵值的行。在下例中,order_part 表建立一個外鍵引用前面定義的part_sample表。通常情況下,order_part在order表上也有一個外鍵,下面只不過是一個簡單示例。
CREATE TABLE order_part
(
order_nmbr int,
part_nmbr int
FOREIGN KEY REFERENCES part_sample(part_nmbr) ON DELETE NO ACTION,
qty_ordered int
)
如果一個外鍵值沒有候選鍵,則不能插入帶該值(NULL除外)的行。如果嘗試刪除現有外鍵指向的行,ON DELETE子句將控制所采取的操作。
ON DELETE子句有兩個選項:
A、NO ACTION指定刪除因錯誤而失敗。
B、CASCADE 指定還將刪除包含指向已刪除行的外鍵的所有行。
如果嘗試更新現有外鍵指向的候選鍵值,ON UPDATE 子句將定義所采取的操作。它也支持NO ACTION和CASCADE選項。
10、列約束和表約束
約束可以是列約束或表約束:
列約束被指定為列定義的一部分,并且僅適用于那個列(前面的示例中的約束就是列約束)。
表約束的聲明與列的定義無關,可以適用于表中一個以上的列。
當一個約束中必須包含一個以上的列時,必須使用表約束。
例如,如果一個表的主鍵內有兩個或兩個以上的列,則必須使用表約束將這兩列加入主鍵內。假設有一個表記錄工廠內的一臺計算機上所發生的事件。假定有幾類事件可以同時發生,但不能有兩個同時發生的事件屬于同一類型。這一點可以通過將type列和time列加入雙列主鍵內來強制執行。
CREATE TABLE factory_process
(
event_type int,
event_time datetime,
event_site char(50),
event_desc char(1024),
CONSTRAINT event_key PRIMARY KEY(event_type,event_time)
)
二、規則
規則是一個向后兼容的功能,用于執行一些與CHECK約束相同的功能。CHECK約束是用來限制列值的首選標準方法。CHECK約束比規則更簡明,一個列只能應用一個規則,但是卻可以應用多個CHECK約束。CHECK約束作為CREATE TABLE 語句的一部分進行指定,而規則以單獨的對象創建,然后綁定到列上。
下例創建一個規則,執行與前面主題中的CHECK約束示例相同的功能。SQL Srver2005 首選的方法是 CHECK 約束。
CREATE RULE id_chk AS @id BETWEEN 0 and 10000
GO
CREATE TABLE cust_sample
(
cust_id int
PRIMARY KEY,
cust_name char(50),
cust_address char(50),
cust_credit_limit money,
)
GO
sp_bindrule id_chk,'cust_sample.cust_id'
GO
再看例子:
Create rule SalaryRule
as @salary >0;
sp_bindrule 'SalaryRule' , 'Employee.Salary'
第一句定義了一個規則叫SalaryRule
進行比較的事物是一個變量
這個變量的值是所檢查的列的值
第二句把規則綁定到某個表的一個列上
規則和ckeck約束很相似,
但是規則只作用在一個列上
一個規則可以綁定在多個列上,但是它不會意識到其他列的存在
check可以定義column1>=column2
取消規則
exec sp_unbindrule 'Employee.Salary'
刪除規則
Drop rule SalaryRule
1:默認值
默認值與default約束類似(有區別的,但是我說不清楚)
先看例子:
create default salarydefault
as 0;
exec sp_binddefault 'salarydefault' , 'employee.salary';
取消默認值:
exec sp_unbinddefault 'employee.salary'
刪除默認值:
drop default 'salarydefault'
外記:
在Create Table 語句的屬性清單后,加上外部碼說明子句,格式為:
FOREIGN KEY <屬性名表1> REFERENCES <表名>(<屬性名表2>)
eno char(4) CONSTRAINT PK_employee PRIMARY KEY,
dno char(4)CONSTRAINT FK_employee FOREIGN KEY REFERENCES department(dno);
ALTER TABLE語句來更新與屬性或表有關的各種約束。如:
ALTER TABLE employee DROP CONSTRAINT FK_employee;
ALER TABLE Salary ADD CONSTRAINT RightSalary CHECK(Insure+Fund<Rest);