SQL Server中Check約束的學(xué)習(xí)教程
0.什么是Check約束?
CHECK約束指在表的列中增加額外的限制條件。
注: CHECK約束不能在VIEW中定義。CHECK約束只能定義的列必須包含在所指定的表中。CHECK約束不能包含子查詢。
創(chuàng)建表時(shí)定義CHECK約束
1.1 語(yǔ)法:
CREATE TABLE table_name ( column1 datatype null/not null, column2 datatype null/not null, ... CONSTRAINT constraint_name CHECK (column_name condition) [DISABLE] );
其中,DISABLE關(guān)鍵之是可選項(xiàng)。如果使用了DISABLE關(guān)鍵字,當(dāng)CHECK約束被創(chuàng)建后,CHECK約束的限制條件不會(huì)生效。
1.2 示例1:數(shù)值范圍驗(yàn)證
create table tb_supplier ( supplier_id number, supplier_name varchar2(50), contact_name varchar2(60), /*定義CHECK約束,該約束在字段supplier_id被插入或者更新時(shí)驗(yàn)證,當(dāng)條件不滿足時(shí)觸發(fā)。*/ CONSTRAINT check_tb_supplier_id CHECK (supplier_id BETWEEN 100 and 9999) );
驗(yàn)證:
在表中插入supplier_id滿足條件和不滿足條件兩種情況:
--supplier_id滿足check約束條件,此條記錄能夠成功插入 insert into tb_supplier values(200, 'dlt','stk'); --supplier_id不滿足check約束條件,此條記錄能夠插入失敗,并提示相關(guān)錯(cuò)誤如下 insert into tb_supplier values(1, 'david louis tian','stk');
不滿足條件的錯(cuò)誤提示:
Error report - SQL Error: ORA-02290: check constraint (502351838.CHECK_TB_SUPPLIER_ID) violated 02290. 00000 - "check constraint (%s.%s) violated" *Cause: The values being inserted do not satisfy the named check
1.3 示例2:強(qiáng)制插入列的字母為大寫(xiě)
create table tb_products ( product_id number not null, product_name varchar2(100) not null, supplier_id number not null, /*定義CHECK約束check_tb_products,用途是限制插入的產(chǎn)品名稱必須為大寫(xiě)字母*/ CONSTRAINT check_tb_products CHECK (product_name = UPPER(product_name)) );
驗(yàn)證:
在表中插入product_name滿足條件和不滿足條件兩種情況:
--product_name滿足check約束條件,此條記錄能夠成功插入 insert into tb_products values(2, 'LENOVO','2'); --product_name不滿足check約束條件,此條記錄能夠插入失敗,并提示相關(guān)錯(cuò)誤如下 insert into tb_products values(1, 'iPhone','1');
不滿足條件的錯(cuò)誤提示:
SQL Error: ORA-02290: check constraint (502351838.CHECK_TB_PRODUCTS) violated 02290. 00000 - "check constraint (%s.%s) violated" *Cause: The values being inserted do not satisfy the named check
2. ALTER TABLE定義CHECK約束
2.1 語(yǔ)法
ALTER TABLE table_name ADD CONSTRAINT constraint_name CHECK (column_name condition) [DISABLE];
其中,DISABLE關(guān)鍵之是可選項(xiàng)。如果使用了DISABLE關(guān)鍵字,當(dāng)CHECK約束被創(chuàng)建后,CHECK約束的限制條件不會(huì)生效。
2.2 示例準(zhǔn)備
drop table tb_supplier; --創(chuàng)建實(shí)例表 create table tb_supplier ( supplier_id number, supplier_name varchar2(50), contact_name varchar2(60) );
2.3 創(chuàng)建CHECK約束
--創(chuàng)建check約束 alter table tb_supplier add constraint check_tb_supplier check (supplier_name IN ('IBM','LENOVO','Microsoft'));
2.4 驗(yàn)證
--supplier_name滿足check約束條件,此條記錄能夠成功插入 insert into tb_supplier values(1, 'IBM','US'); --supplier_name不滿足check約束條件,此條記錄能夠插入失敗,并提示相關(guān)錯(cuò)誤如下 insert into tb_supplier values(1, 'DELL','HO');
不滿足條件的錯(cuò)誤提示:
SQL Error: ORA-02290: check constraint (502351838.CHECK_TB_SUPPLIER) violated 02290. 00000 - "check constraint (%s.%s) violated" *Cause: The values being inserted do not satisfy the named check
3. 啟用CHECK約束
3.1 語(yǔ)法
ALTER TABLE table_name ENABLE CONSTRAINT constraint_name;
3.2 示例
drop table tb_supplier; --重建表和CHECK約束 create table tb_supplier ( supplier_id number, supplier_name varchar2(50), contact_name varchar2(60), /*定義CHECK約束,該約束盡在啟用后生效*/ CONSTRAINT check_tb_supplier_id CHECK (supplier_id BETWEEN 100 and 9999) DISABLE ); --啟用約束 ALTER TABLE tb_supplier ENABLE CONSTRAINT check_tb_supplier_id;
3.3使用Check約束提升性能
在SQL Server中,SQL語(yǔ)句的執(zhí)行是依賴查詢優(yōu)化器生成的執(zhí)行計(jì)劃,而執(zhí)行計(jì)劃的好壞直接關(guān)乎執(zhí)行性能。
在查詢優(yōu)化器生成執(zhí)行計(jì)劃過(guò)程中,需要參考元數(shù)據(jù)來(lái)盡可能生成高效的執(zhí)行計(jì)劃,因此元數(shù)據(jù)越多,則執(zhí)行計(jì)劃更可能會(huì)高效。所謂需要參考的元數(shù)據(jù)主要包括:索引、表結(jié)構(gòu)、統(tǒng)計(jì)信息等,但還有一些不是很被注意的元數(shù)據(jù),其中包括本文闡述的Check約束。
圖1.簡(jiǎn)單查詢
查詢優(yōu)化器在生成執(zhí)行計(jì)劃之前有一個(gè)階段叫做代數(shù)樹(shù)優(yōu)化,比如說(shuō)下面這個(gè)簡(jiǎn)單查詢:
查詢優(yōu)化器意識(shí)到1=2這個(gè)條件是永遠(yuǎn)不相等的,因此不需要返回任何數(shù)據(jù),因此也就沒(méi)有必要掃描表,從圖1執(zhí)行計(jì)劃可以看出僅僅掃描常量后確定了1=2永遠(yuǎn)為false后,就可完成查詢。
那么Check約束呢?
Check約束可以確保一列或多列的值符合表達(dá)式的約束。在某些時(shí)候,Check約束也可以為優(yōu)化器提供信息,從而優(yōu)化性能,比如看圖二的例子。
圖2.有Check約束的列提升查詢性能
圖2是一個(gè)簡(jiǎn)單的例子,有時(shí)候在分區(qū)視圖中應(yīng)用Check約束也會(huì)提升性能,測(cè)試代碼如下:
CREATE TABLE [dbo].[Test2007]( [ProductReviewID] [int] IDENTITY(1,1) NOT NULL, [ReviewDate] [datetime] NOT NULL ) ON [PRIMARY] GO ALTER TABLE [dbo].[Test2007] WITH CHECK ADD CONSTRAINT [CK_Test2007] CHECK (([ReviewDate]>='2007-01-01' AND [ReviewDate]'2007-12-31')) GO ALTER TABLE [dbo].[Test2007] CHECK CONSTRAINT [CK_Test2007] GO CREATE TABLE [dbo].[Test2008]( [ProductReviewID] [int] IDENTITY(1,1) NOT NULL, [ReviewDate] [datetime] NOT NULL ) ON [PRIMARY] GO ALTER TABLE [dbo].[Test2008] WITH CHECK ADD CONSTRAINT [CK_Test2008] CHECK (([ReviewDate]>='2008-01-01' AND [ProductReviewID]'2008-12-31')) GO ALTER TABLE [dbo].[Test2008] CHECK CONSTRAINT [CK_Test2008] GO INSERT INTO [Test2008] values('2008-05-06') INSERT INTO [Test2007] VALUES('2007-05-06') CREATE VIEW testPartitionView AS SELECT * FROM Test2007 UNION SELECT * FROM Test2008 SELECT * FROM testPartitionView WHERE [ReviewDate]='2007-01-01' SELECT * FROM testPartitionView WHERE [ReviewDate]='2008-01-01' SELECT * FROM testPartitionView WHERE [ReviewDate]='2010-01-01'
我們針對(duì)Test2007和Test2008兩張表結(jié)構(gòu)一模一樣的表做了一個(gè)分區(qū)視圖。并對(duì)日期列做了Check約束,限制每張表包含的數(shù)據(jù)都是特定一年內(nèi)的數(shù)據(jù)。當(dāng)我們對(duì)視圖進(jìn)行查詢并給定不同的篩選條件時(shí),可以看到結(jié)果如圖3所示。
圖3.不同的條件產(chǎn)生不同的執(zhí)行計(jì)劃
由圖3可以看出,當(dāng)篩選條件為2007年時(shí),自動(dòng)只掃描2007年的表,2008年的表也是同樣。而當(dāng)查詢范圍超出了2007和2008年的Check約束后,查詢優(yōu)化器自動(dòng)判定結(jié)果為空,因此不做任何IO操作,從而提升了性能。
結(jié)論
在Check約束條件為簡(jiǎn)單的情況下(指的是約束限制在單列且表達(dá)式中不包含函數(shù)),不僅可以約束數(shù)據(jù)完整性,在很多時(shí)候還能夠提供給查詢優(yōu)化器信息從而提升性能。
4. 禁用CHECK約束
4.1 語(yǔ)法
ALTER TABLE table_name DISABLE CONSTRAINT constraint_name;
4.2 示例
--禁用約束 ALTER TABLE tb_supplier DISABLE CONSTRAINT check_tb_supplier_id;
5. 約束詳細(xì)信息查看
語(yǔ)句:
--查看約束的詳細(xì)信息 select constraint_name,--約束名稱 constraint_type,--約束類型 table_name,--約束所在的表 search_condition,--約束表達(dá)式 status--是否啟用 from user_constraints--[all_constraints|dba_constraints] where constraint_name='CHECK_TB_SUPPLIER_ID';
6. 刪除CHECK約束
6.1 語(yǔ)法
ALTER TABLE table_name DROP CONSTRAINT constraint_name;
6.2 示例
ALTER TABLE tb_supplier DROP CONSTRAINT check_tb_supplier_id;
版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。