一、SQL約束 約束定義關于列中允許值的規則,是強制完整性的標準機制。
使用約束優先于使用觸發器、規則和默認值。查詢優化器也使用約束定義生成高性能的查詢執行計劃。 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); |