SELECT TOP (1000) [Patient_ID]
,[Disease_diagnosed]
,[Diagnose_Date]
,[Is_Recovered]
FROM [TEST001].[dbo].[Diagnosis]
OK,如果我們要用日期區間為條件來找出這筆 ID為 1 的資料,而我們第一次嘗試:
SELECT TOP (1000) [Patient_ID]
,[Disease_diagnosed]
,[Diagnose_Date]
,[Is_Recovered]
FROM [TEST001].[dbo].[Diagnosis]
where [Diagnose_Date] between 2024-07-05 and 2024-07-06
就會發現這樣查詢是找不出東西的,因為SQL Server 沒有正確地把這個 2024/07/05 識別成一個日期的值,要讓SQL server 正確的識別,必須加上單引號 ‘ 把日期框住。
另外一個狀況是這樣的:
SELECT TOP (1000) [Patient_ID]
,[Disease_diagnosed]
,[Diagnose_Date]
,[Is_Recovered]
FROM [TEST001].[dbo].[Diagnosis]
where [Diagnose_Date] = '2024-07-05'
SELECT TOP (1000) [Patient_ID]
,[Disease_diagnosed]
,[Diagnose_Date]
,[Is_Recovered]
FROM [TEST001].[dbo].[Diagnosis]
WHERE [Diagnose_Date] >= '2024-07-05'
AND [Diagnose_Date] < '2024-07-06';
另外值得注意一點:由於 between 是包含頭尾的關係。 使用這種寫法要特別留意頭尾該不該被包含進來:
SELECT TOP (1000) [Patient_ID]
,[Disease_diagnosed]
,[Diagnose_Date]
,[Is_Recovered]
FROM [TEST001].[dbo].[Diagnosis]
WHERE [Diagnose_Date] >= '2024-07-05'
AND [Diagnose_Date] < '2024-07-06';
SELECT [Patient_ID]
FROM [TEST001].[dbo].[Patient]
where [Hospitalized]='Y'
Intersect
SELECT [Patient_ID]
FROM [TEST001].[dbo].[Diagnosis]
where [Is_Recovered]='Y'
SELECT * from [Patient]
WHERE [Patient_ID] IN
(
SELECT [Patient_ID]
FROM [TEST001].[dbo].[Patient]
where [Hospitalized]='Y'
Intersect
SELECT [Patient_ID]
FROM [TEST001].[dbo].[Diagnosis]
where [Is_Recovered]='Y'
)
像這樣,透過我們使用 set operator 所查詢的結果作為查詢條件去查詢 [Patient] 這張表。 我們就成功地把正在住院但已經痊癒的病人的完整資料叫出來了。 而除了在 WHERE 子句中進行子查詢之外,也可以在 FROM 子句中進行子查詢。 我們將會在之後介紹 Group by 與 Having 時一起介紹。
SELECT TOP (1000) [Patient_ID]
,[Patient_Name]
,[Patient_Gender]
,[Patient_Height]
,[Patient_Weight]
,[Hospitalized]
FROM [TEST001].[dbo].[Patient]
where [Hospitalized]='Y'
SELECT TOP (1000) [Patient_ID]
,[Disease_diagnosed]
,[Diagnose_Date]
,[Is_Recovered]
FROM [TEST001].[dbo].[Diagnosis]
where [Is_Recovered]='Y'
而當我們要開始找正在住院但已經痊癒的病人的時候,我們就要用到第一個 set operator: 交集 Intersect。 而當我們使用 set operator 時,要注意的是,兩段 Query 的欄位數必須是一樣的。
SELECT [Patient_ID]
FROM [TEST001].[dbo].[Patient]
where [Hospitalized]='Y'
Intersect
SELECT [Patient_ID]
FROM [TEST001].[dbo].[Diagnosis]
where [Is_Recovered]='Y'
像這樣,我們就找出了已經痊癒又住院中的 Patient_ID
接下來我們介紹第二個 set operator:Union,Union 是聯集,也就是 或 的概念。
SELECT [Patient_ID]
FROM [TEST001].[dbo].[Patient]
where [Hospitalized]='Y'
UNION
SELECT [Patient_ID]
FROM [TEST001].[dbo].[Diagnosis]
where [Is_Recovered]='Y'
將剛才放在兩段Query之間的 Intersect 換成 Union,我們就可以得到 在住院的病患和痊癒的病患的聯集,也就是這個病患在住院或是已經痊癒。 不過要留意一件事情:在我們最一開始的兩段 Query 中,查詢的結果是有 20 筆的 但這裡的 Union 的結果只有 15 筆,這是因為 這三個 Set operator 都會預設去掉重複值。 而在這些 Set operator 中,只有 Union 可以透過加上 All 來避免去除重複。
SELECT [Patient_ID]
FROM [TEST001].[dbo].[Patient]
where [Hospitalized]='Y'
except
SELECT [Patient_ID]
FROM [TEST001].[dbo].[Diagnosis]
where [Is_Recovered]='Y'
Foreign Key 約束會將能進入一個欄位的資料局限於是一個會另一張表的特定欄位裡所有的資料的約束,當我們輸入資料時, SQL Server 就會參照另一個欄位,確認那個欄位有這筆資料才會成功,沒有這筆資料時,該筆資料就沒辦法輸入。而我們稱被參照的來源資料表為 Parent,實際套用約束的資料表則是稱為 Child 所以當我們要建立與測試 Foreign Key 約束前,我們要先建立這個約束要參照資料表與欄位,這個欄位必須是該資料表的 Primary Key,並且這兩個資料型態必須相同。 請打開 New Query 後,複製下列文字並按下 F5 執行:
Create Table Foreign_Key_test_Parent
(
Student_ID int Not Null Primary Key,
Student_Name nvarchar(50),
Date_of_Birth date
)
INSERT INTO Foreign_Key_test_Parent (Student_ID,Student_Name,Date_of_Birth)Values
('1001','Jeff','2022/02/13'),
('1002','Lily','2022/02/14'),
('1003','Tochter','2022/02/15')
SELECT TOP (10) * From Foreign_Key_test_Parent
另一種則是透過 information schema 查詢,請打開 New Query 後,複製下列文字並按下 F5 執行:
Select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE
刪除 Foreign Key 則是使用 Alter table 資料表名稱 Drop constraint Foreign Key 名稱,
請打開 New Query 後,複製下列文字並按下 F5 執行:
Alter table Foreign_Key_test_Child
Drop constraint Foreign_Key_Student_ID
INSERT INTO Foreign_Key_test_Child (Student_ID,Course_ID,Score)Values
('1004','0020','D')
SELECT TOP (10) * From Foreign_Key_test_Child
就可以看到約束消失,剛才因為約束無法被 insert 的資料可以成功insert 了。
而同樣使用 Alter Table 指令則可以再把 Foreign Key 加回來, 請打開 New Query 後,複製下列文字並按下 F5 執行:
Delete Foreign_Key_test_Child
Alter table Foreign_Key_test_Child
ADD constraint Foreign_Key_Student_ID
Foreign Key(Student_ID) References Foreign_Key_test_Parent(Student_ID);
INSERT INTO Foreign_Key_test_Child (Student_ID,Course_ID,Score)Values
('1004','0020','D')