[SQL]使用Constraint

[SQL]使用Constraint

練習一下


-- 資料來源:德瑞克老師的上課筆記+自行修改
USE ProductDB
GO

-- 使用 DEFAULT 「條件約束(Constraint)」
-- 從正式表格隨機選取員工編號後新增測試資料
-- 建立測試表格
IF  EXISTS
(SELECT *
 FROM
	 sys.objects
 WHERE
	 object_id = object_id(N'[dbo].[EMPLOYEE_TEST_DATA]')
	 AND type IN (N'U')) DROP TABLE [dbo].[EMPLOYEE_TEST_DATA]
GO
CREATE TABLE [dbo].[EMPLOYEE_TEST_DATA]
(
[STAFF] [nvarchar](6)PRIMARY KEY,
[NOTE][nvarchar](30)DEFAULT ('這是林大貓的測試資料'),
[CEATETIME][datetime] DEFAULT getdate()
);
GO

-- 檢查測試表格
SELECT *
FROM
	dbo.EMPLOYEE_TEST_DATA

-- 隨機選取十筆資料當作測試資料
INSERT [dbo].[EMPLOYEE_TEST_DATA] (STAFF)
SELECT TOP 10 STAFF
FROM
	dbo.EMPLOYEE
ORDER BY
	newid()
GO

-- 查詢測試表格資料
SELECT *
FROM
	dbo.EMPLOYEE_TEST_DATA

-- CHECK 條件約束限制資料行接受的值,藉此強制值域完整性。
-- 可用於partition table 	
-- 檢查條件:測試表格的備註欄位不得為李大牛
ALTER TABLE [dbo].[EMPLOYEE_TEST_DATA]  
WITH CHECK ADD  
	CONSTRAINT [CK_NAME] CHECK  (([NOTE]<>'李大牛'))
GO

-- 看條件約束是否建立
SELECT name N'物件名稱'
	 , type N'物件類型'
	 , type_desc N'物件類型描述'
	 , definition N'「CHECK」條件約束的 SQL 運算式'
FROM
	sys.check_constraints
WHERE
	parent_object_id = object_id('EMPLOYEE_TEST_DATA')
GO

-- 測試新增跟修改是否會失敗
INSERT INTO [dbo].[EMPLOYEE_TEST_DATA]
VALUES
	(123456, N'李大牛', getdate())

UPDATE [dbo].[EMPLOYEE_TEST_DATA]
SET
	NOTE = N'李大牛'
GO

-- 停用條件約束
ALTER TABLE [dbo].[EMPLOYEE_TEST_DATA] 
	NOCHECK CONSTRAINT ALL
GO

-- 檢查是否停用
SELECT name N'物件名稱'
	 , type N'物件類型'
	 , type_desc N'物件類型描述'
	 , definition N'「CHECK」條件約束的 SQL 運算式'
	 , is_disabled N'CHECK 條件約束已停用'
FROM
	sys.check_constraints
GO

-- Foreign Key 外部索引鍵
-- 主鍵表格新增固定資料
TRUNCATE TABLE [dbo].[EMPLOYEE_TEST_DATA]
GO
INSERT [dbo].[EMPLOYEE_TEST_DATA] (STAFF)
SELECT '123456'
GO

SELECT *
FROM
	dbo.EMPLOYEE_TEST_DATA

-- 建立測試表格(FK)
IF  EXISTS
(SELECT *
 FROM
	 sys.objects
 WHERE
	 object_id = object_id(N'[dbo].[EMPLOYEE_TEST_DATA_FK]')
	 AND type IN (N'U')) DROP TABLE [dbo].[EMPLOYEE_TEST_DATA_FK]
GO
CREATE TABLE [dbo].[EMPLOYEE_TEST_DATA_FK]
(
	[LOGOUTTIME][datetime] DEFAULT getdate(),
	[STAFF] [nvarchar](6)	
);
GO

-- 檢查表格是否建立
SELECT *
FROM
	dbo.EMPLOYEE_TEST_DATA_FK

-- 輸入測試資料
INSERT dbo.EMPLOYEE_TEST_DATA_FK (STAFF)
SELECT STAFF
FROM
	dbo.EMPLOYEE_TEST_DATA
GO
-- 檢查資料是否匯入
SELECT *
FROM
	dbo.EMPLOYEE_TEST_DATA_FK		
	
-- 建立Foreign Key
-- NO ACTION,違反時,此動作產生錯誤,並復原(Rollback)。
ALTER TABLE dbo.EMPLOYEE_TEST_DATA_FK ADD CONSTRAINT
	FK_EMPLOYEE_TEST_DATA FOREIGN KEY
	(
	STAFF
	) REFERENCES dbo.EMPLOYEE_TEST_DATA
	(
	STAFF
	) ON UPDATE  NO ACTION 
	 ON DELETE  NO ACTION
GO

-- 檢查Foreign Key是否建立
SELECT name N'物件名稱'
	 , type_desc N'物件描述'
	 , object_name(referenced_object_id) N'主索引資料表'
	 , object_name(parent_object_id) N'外部索引資料表'
	 , delete_referential_action_desc N'在進行刪除時,宣告的參考動作之描述'
	 , update_referential_action_desc N'在進行更新時,宣告的參考動作之描述'
FROM
	sys.foreign_keys
GO

-- 測試新增跟修改外鍵表格資料是否會失敗
-- (999999為不存在的員工編號)
INSERT INTO [dbo].[EMPLOYEE_TEST_DATA_FK] (STAFF)
VALUES
	('999999')

UPDATE [dbo].[EMPLOYEE_TEST_DATA_FK]
SET
	STAFF = '999999'
GO

-- 檢查資料
SELECT *
FROM
	dbo.EMPLOYEE_TEST_DATA
SELECT *
FROM
	dbo.EMPLOYEE_TEST_DATA_FK

-- 建立Foreign Key
-- CASCADE,自動刪除或更新「外部索引鍵資料表」上所對應的資料。
ALTER TABLE dbo.EMPLOYEE_TEST_DATA_FK
	DROP CONSTRAINT FK_EMPLOYEE_TEST_DATA
ALTER TABLE dbo.EMPLOYEE_TEST_DATA_FK ADD CONSTRAINT
	FK_EMPLOYEE_TEST_DATA FOREIGN KEY
	(
	STAFF
	) REFERENCES dbo.EMPLOYEE_TEST_DATA
	(
	STAFF
	) ON UPDATE  CASCADE 
	 ON DELETE  CASCADE
GO

-- 檢查Foreign Key是否建立
SELECT name N'物件名稱'
	 , type_desc N'物件描述'
	 , object_name(referenced_object_id) N'主索引資料表'
	 , object_name(parent_object_id) N'外部索引資料表'
	 , delete_referential_action_desc N'在進行刪除時,宣告的參考動作之描述'
	 , update_referential_action_desc N'在進行更新時,宣告的參考動作之描述'
FROM
	sys.foreign_keys
GO

-- 測試修改跟跟刪除主鍵表格資料是否會將外鍵表格的資料異動
-- (999999為不存在的員工編號)
UPDATE [dbo].[EMPLOYEE_TEST_DATA]
SET
	STAFF = '999999'
WHERE
	STAFF = '123456'

DELETE
FROM
	[dbo].[EMPLOYEE_TEST_DATA]
WHERE
	STAFF = '999999'
GO

-- 檢查資料
SELECT *
FROM
	dbo.EMPLOYEE_TEST_DATA
SELECT *
FROM
	dbo.EMPLOYEE_TEST_DATA_FK

-- 刪除測試資料
ALTER TABLE dbo.EMPLOYEE_TEST_DATA_FK
	DROP CONSTRAINT FK_EMPLOYEE_TEST_DATA
DROP TABLE dbo.EMPLOYEE_TEST_DATA_FK
DROP TABLE dbo.EMPLOYEE_TEST_DATA
GO