完整性約束數據庫
定義主碼約束數據結構
Sno char(10) PRIMARY KEY; // 或者是在表的最後 PRIMARY KEY (Sno);
定義外碼約束函數
FOREIGN KEY (Sno) REFERENCES student (Sno), FOREIGN KEY (Cno) REFERENCES course (Cno)
刪除表spa
DROP TABLE student;
修改表的定義code
>1 ALTER TABLE student >2 ALTER COLUMN Sno varchar(20); // 修改列定義 >1 ALTER TABLE student >2 ADD job varchar(20) NULL; // 添加列 >1 ALTER TABLE student >2 DROP COLUMN job; // 刪除列 >1 ALTER TABLE student >2 ADD constraint CK_stuAge CHECK(Sage between 15 and 40) // 增長約束 >1 ALTER TABLE student >2 DROP contstraint CK_stuAge; // 刪除約束
創表完成以後的約束補充和修改排序
假設如今有了work僱員表和job工做表。圖片
// 建立 1> CREATE TABLE work ( 2> workerid char(7) NOT NULL, 3> workername char(10) , 4> worknum char(8), 5> money int, 6> phone char(11) NOT NULL 7> ); 8> go 1> CREATE TABLE job( 2> worknum char(8), 3> mixmoney int, 4> maxmoney int, 5> ); 6> go
而後爲其補充一些必要的約束字符串
主碼約束
// 爲work表添加主碼約束 1> ALTER TABLE work 2> ADD CONSTRAINT M_PK // M_PK是本身起的約束名 3> PRIMARY KEY(workerid); 4> go
// 爲job表添加主碼約束 // 可是以前沒有爲該列加 NOT NULL ,因此先添加一個NOT NULL的約束 1> ALTER TABLE job 2> ALTER COLUMN worknum char(8) NOT NULL; 3> go // 在爲job表添加主碼約束 1> ALTER TABLE job 2> ADD CONSTRAINT PK_JOB 3> PRIMARY KEY (worknum); 4> go 1>
UNIQUE 約束
// 爲僱員表worker的 phone 添加UNIQUE約束,使得其值不能有重複 1> ALTER TABLE work 2> ADD CONSTRAINT WORK_UK 3> UNIQUE (phone); 4> go 1>
外碼約束
// 爲僱員表work 的 工做編號worknum 添加外碼約束 1> ALTER TABLE work 2> ADD CONSTRAINT FK_JOBID 3> FOREIGN KEY (worknum) REFERENCES job (worknum); 4> go 1>
DEFAULT 約束
// 爲僱員的工資提默認值 1> ALTER TABLE work 2> ADD CONSTRAINT DF_work 3> DEFAULT 1000 FOR money; 4> go 1>
CHECK 約束
// 僱員工資表的工資最低是1000 1> ALTER TABLE work 2> ADD CONSTRAINT CHK_money 3> CHECK (money>=1000); 4> go 1> // 最低工資 < 最高工資 1> ALTER TABLE job 2> ADD CONSTRAINT CHK_job 3> CHECK (mixmoney<=maxmoney); 4> go 1>
插入數據
// 先往job表中插入一條數據 1> INSERT INTO job VALUES ('1',1000,1900); 2> go (1 行受影響) // 在往work中插入幾條數據 1> INSERT INTO work VALUES ('1','張錦傑','1',1400,'13752127826'); 2> go (1 行受影響)
數據查詢SELECT
查詢表的所有數學
// 查詢work表所有信息 1> SELECT * FROM work; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D張錦傑 D1 D 1400D13752127826 (1 行受影響)
// 查詢job表所有信息 1> SELECT * FROM job; 2> go worknum Dmixmoney Dmaxmoney --------D-----------D----------- 1 D 1000D 1900 (1 行受影響)
爲了配如下的操做,須要多添加幾條信息it
// 查詢以下 1> SELECT * FROM work; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D張錦傑 D1 D 1400D13752127826 2 D長官 D1 D 1600D1224123314 3 D妹妹 D1 D 1300D122432414 4 D妹ds妹 D1 D 1700D12223323414 5 D撒愛 D1 D 1900D1223414 6 D張愛愛 D1 D 1100D1324977734 (6 行受影響)
查詢某幾列
1> SELECT workerid,workername FROM work; 2> go workeridDworkername --------D---------- 1 D張錦傑 2 D長官 3 D妹妹 4 D妹ds妹 5 D撒愛 6 D張愛愛 (6 行受影響)
查詢出通過計算的列
1> SELECT workerid, money+1000 FROM work; 2> go workeridD --------D----------- 1 D 2400 2 D 2600 3 D 2300 4 D 2700 5 D 2900 6 D 2100 (6 行受影響) // 會產生一個無名的列
常量列
1> SELECT workerid, '我是常量列成員', money+1000 FROM work; 2> go workeridD D --------D--------------D----------- 1 D我是常量列成員 D 2400 2 D我是常量列成員 D 2600 3 D我是常量列成員 D 2300 4 D我是常量列成員 D 2700 5 D我是常量列成員 D 2900 6 D我是常量列成員 D 2100 (6 行受影響) // 產生兩個無名列
爲無名列指定名字
1> SELECT workerid AS 主鍵, '我是常量內容' AS 常量 , money+1000 AS 總金額 FROM work; 2> go 主鍵 D常量 D總金額 -------D------------D----------- 1 D我是常量內容 D 2400 2 D我是常量內容 D 2600 3 D我是常量內容 D 2300 4 D我是常量內容 D 2700 5 D我是常量內容 D 2900 6 D我是常量內容 D 2100 (6 行受影響)
去除掉取值相同的行
>1 SELECT DISTINCT Sno FROM SC; >2 go // 去除掉重複的行,使用了關鍵字DISTINCT
查詢知足條件的元組
查詢條件 | 謂詞 |
---|---|
比較 | = > < <= >= != 以及 NOT+前面的比較用算符 |
肯定範圍 | BETWEEN AND , NOT BETWEEN AND |
肯定集合 | IN , NOTIN |
字符匹配 | LIKE, NOT LIKE |
空值 | IS NULL, IS NOT NULL |
多重條件 | AND, OR |
1> SELECT * FROM work WHERE money=1400; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D張錦傑 D1 D 1400D13752127826 (1 行受影響) // 取反操做:NOT money < 1200 // 正向操做:money >= 1200 // 須要注意的:取反操做比正向操做執行效率低,由於取反先是執行正向操做,而後從全體數據中排除這部分。所以取反操做須要通過兩個步驟。
1> SELECT * FROM work WHERE money BETWEEN 1200 AND 1700; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D張錦傑 D1 D 1400D13752127826 2 D長官 D1 D 1600D1224123314 3 D妹妹 D1 D 1300D122432414 4 D妹ds妹 D1 D 1700D12223323414 (4 行受影響) // BETWEEN 1200 AND 1700; 至關因而 同時知足 >=1200 <=1700 // 相反操做 1> SELECT * FROM work WHERE money NOT BETWEEN 1200 AND 1700; 2> GO workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 5 D撒愛 D1 D 1900D1223414 6 D張愛愛 D1 D 1100D1324977734 (2 行受影響)
對於日期的比較:
SELECT * FROM books WHERE time BETWEEN '2009/3/12' AND '2010/4/23'; // 對於日期類型的常量,須要用單引號引發來,而且年月日之間要用 '/' '-' 分割符來分割
1> SELECT * FROM work WHERE money IN ('1400','1500','1700'); 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D張錦傑 D1 D 1400D13752127826 4 D妹ds妹 D1 D 1700D12223323414 (2 行受影響)
// 可使用LIKE進行模糊查找
// 匹配姓張的人 1> SELECT * FROM work WHERE workername LIKE '張%'; 4> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D張錦傑 D1 D 1400D13752127826 6 D張愛愛 D1 D 1100D1324977734 (2 行受影響)
//匹配姓張、李、撒的人 1> SELECT * FROM work WHERE workername LIKE '[張李撒]%'; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D張錦傑 D1 D 1400D13752127826 5 D撒愛 D1 D 1900D1223414 6 D張愛愛 D1 D 1100D1324977734 (3 行受影響)
// 不姓張也不姓王的 1> SELECT * FROM work WHERE workername NOT LIKE '[張王]%'; 2> go 或者 1> SELECT * FROM work WHERE workername LIKE '[^張王]%'; 2> go
1> SELECT * FROM work WHERE workername LIKE '[張_]'; // 姓張且是兩個字 2> go
// 去掉指定列的尾隨的空格 1> SELECT * FROM work WHERE workername LIKE '[張__]'; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- (0 行受影響) // 爲何是無呢? // 由於咱們實際數據庫的時候,給workername是char定長類型的,所以,若是不夠定長,就用空格填充了,這就使得匹配沒法成功。 如何解決呢? SQL Server 提供了 rtrim(列名) 來去掉尾隨的空格 1> SELECT * FROM work WHERE rtrim(workername) LIKE '[張_]%'; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D張錦傑 D1 D 1400D13752127826 6 D張愛愛 D1 D 1100D1324977734 (2 行受影響)
// 查詢最後一位不是 2.3.5 1> SELECT * FROM work WHERE workername LIKE '%[^235]'; 2> go
// 轉義字符 ESCAPE 關鍵字 1> SELECT * FROM work WHERE workername LIKE '%30!%%' ESCAPE '!'; 2> go // 以!轉義% 意思是查找包含30%的字符串 1> SELECT * FROM work WHERE workername LIKE '%!_%' ESCAPE '!'; 2> go // 以!轉義_ 意思是查找包含30%的字符串
// SELECT * FROM SC WHERE grade IS NOT NULL; SELECT * FROM SC WHERE grade IS NULL;
就是 AND
和 OR
SELECT Sname FROM Student WHERE Sdep = '計算機' AND Sage < 20 // AND 的 優先級比 OR 高,所以須要使用括號 SELECT Sname FROM Student WHERE ( Sdep = '計算機' OR Sdep = '信息') AND Sage < 20
排序
1> SELECT * FROM work ORDER BY money ASC; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 6 D張愛愛 D1 D 1100D1324977734 3 D妹妹 D1 D 1300D122432414 1 D張錦傑 D1 D 1400D13752127826 2 D長官 D1 D 1600D1224123314 4 D妹ds妹 D1 D 1700D12223323414 5 D撒愛 D1 D 1900D1223414 (6 行受影響)
1> SELECT * FROM work ORDER BY money DESC; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 5 D撒愛 D1 D 1900D1223414 4 D妹ds妹 D1 D 1700D12223323414 2 D長官 D1 D 1600D1224123314 1 D張錦傑 D1 D 1400D13752127826 3 D妹妹 D1 D 1300D122432414 6 D張愛愛 D1 D 1100D1324977734 (6 行受影響)
使用聚合函數來彙總數據
SQL提供的聚合函數有:
// 元組總個數 1> SELECT COUNT(*) FROM work; 2> go ----------- 6 (1 行受影響) // 統計本列非空值個數 1> SELECT COUNT(DISTINCT money) FROM work; 2> go ----------- 6 (1 行受影響) // 設置列名 1> SELECT COUNT(*) AS 工人數 , AVG(money) AS 平均收入 FROM work; 2> go 工人數 D平均收入 -----------D----------- 6D 1500 (1 行受影響) // 使用MAX 和 MIN 1> SELECT MAX(money) AS '最高收入' , MIN(money) AS '最低收入' FROM work; 2> go 最高收入 D最低收入 -----------D----------- 1900D 1100 (1 行受影響)
對查詢結果進行分組統計
// 如今work表是這個樣子 1> SELECT * FROM work; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D張錦傑 D1 D 1400D13752127826 2 D長官 D1 D 1600D1224123314 3 D妹妹 D1 D 1300D122432414 4 D妹ds妹 D1 D 1700D12223323414 5 D撒愛 D1 D 1900D1223414 6 D張愛愛 D1 D 1100D1324977734 7 D大蘇打 D2 D 1500D341212312 8 D阿斯頓 D2 D 1600D3123123 9 D誤區二 D2 D 1700D32424 // 首先對員工表進行按照職位分組,分爲兩組,而後統計每組的數據 1> SELECT COUNT(*) AS 職位員工數 ,AVG(money) 平均收入 2> FROM work GROUP BY worknum; 3> go 職位員工數 D平均收入 -----------D----------- 6D 1500 3D 1600 (2 行受影響) 1> // 再來一次 1> SELECT worknum, COUNT(*) AS 職位員工數 ,AVG(money) 平均收入 2> FROM work GROUP BY worknum; 3> go worknum D職位員工數 D平均收入 --------D-----------D----------- 1 D 6D 1500 2 D 3D 1600 (2 行受影響) // 選擇每一個系的女生的人數 // 再來一個小李子 SELECT Sdept, Count(*) 女生人數 FROM student WHERE Sex = '女' GROUP BY Sdep;
使用HAVING子句
HAVING 語句對分組後的數據在進行篩選,可使用統計函數,可是在WHERE 語句中是沒法使用統計函數的。
// 拿書上的例子來講 SELECT Sno , COUNT(*) AS 選課門數 FROM SC GROUP BY Sno HAVING COUNT(*) >3; // 查詢選修了三門以上的學生的學號和選課數
多表鏈接查詢
鏈接查詢包括內鏈接、外鏈接、交叉鏈接,在這裏咱們只涉及內鏈接、 和外鏈接
// 這裏咱們須要建立三張表 // 學生表 1> CREATE TABLE student( 2> Sno varchar(8) PRIMARY KEY, 3> Sname varchar(10) NOT NULL, 4> Sage tinyint, 5> Ssex char(2), 6> Sdept char(20) 7> ); 8> go 1>var // 課程表 1> CREATE TABLE course( 2> Cno varchar(6) PRIMARY KEY, 3> Cname varchar(10) NOT NULL, 4> Credit tinyint, 5> Semester tinyint, 6> ); 7> go // 選課表 1> CREATE TABLE SC( 2> Sno varchar(8) NOT NULL, 3> Cno varchar(6) NOT NULL, 4> grade tinyint , 5> PRIMARY KEY(Sno, Cno), 6> FOREIGN KEY(Sno) REFERENCES student (Sno), 7> FOREIGN KEY(Cno) REFERENCES course (Cno) 8> ); 9> go 1> // 而後小編在數據庫中添加了幾條數據
// 將student 和 SC 鏈接 1> SELECT * FROM student INNER JOIN SC 2> ON student.Sno = SC.Sno; 3> go Sno DSname DSageDSsexDSdept DSno DCno Dgrade --------D----------D----D----D--------------------D--------D------D----- 13212311D張海 D 22D男 D數學系 D13212311Dc02 D NULL 13212311D張海 D 22D男 D數學系 D13212311Dc04 D 89 16101132D李勇 D 19D男 D計算機系 D16101132Dc01 D 43 16101132D李勇 D 19D男 D計算機系 D16101132Dc02 D NULL 16101132D李勇 D 19D男 D計算機系 D16101132Dc03 D 78 16101321D張錦傑 D 20D男 D計算機系 D16101321Dc01 D 90 16101321D張錦傑 D 20D男 D計算機系 D16101321Dc03 D 78 16101321D張錦傑 D 20D男 D計算機系 D16101321Dc04 D 78 16123211D吳斌 D 22D男 D信息系 D16123211Dc02 D 23 16123211D吳斌 D 22D男 D信息系 D16123211Dc03 D 65 16123211D吳斌 D 22D男 D信息系 D16123211Dc05 D 78 // 去掉重複的列 1> SELECT student.Sno, Sname, Sage, Ssex,Cno,grade FROM student 2> INNER JOIN SC 3> ON student.Sno = SC.Sno; 4> GO Sno DSname DSageDSsexDCno Dgrade --------D----------D----D----D------D----- 13212311D張海 D 22D男 Dc02 D NULL 13212311D張海 D 22D男 Dc04 D 89 16101132D李勇 D 19D男 Dc01 D 43 16101132D李勇 D 19D男 Dc02 D NULL 16101132D李勇 D 19D男 Dc03 D 78 16101321D張錦傑 D 20D男 Dc01 D 90 16101321D張錦傑 D 20D男 Dc03 D 78 16101321D張錦傑 D 20D男 Dc04 D 78 16123211D吳斌 D 22D男 Dc02 D 23 16123211D吳斌 D 22D男 Dc03 D 65 16123211D吳斌 D 22D男 Dc05 D 78 // 查詢計算機系的學生的選修狀況 1> SELECT Sname, Cno, grade FROM student INNER JOIN SC 2> ON student.Sno = SC.Sno 3> WHERE Sdept = "計算機系"; 4> go Sname DCno Dgrade ----------D------D----- 李勇 Dc01 D 43 李勇 Dc02 D NULL 李勇 Dc03 D 78 張錦傑 Dc01 D 90 張錦傑 Dc03 D 78 張錦傑 Dc04 D 78 (6 行受影響) // 查找計算機系中選修了VB的學生信息 1> SELECT Sname, Cname, grade FROM student JOIN SC ON student.Sno = SC.Sno 2> JOIN course ON course.Cno = SC.Cno 3> WHERE Sdept ="計算機系" 4> AND Cname = "VB"; 5> go Sname DCname Dgrade ----------D----------D----- 李勇 DVB D NULL (1 行受影響) // 統計每一個系的學生考試平均成績 1> SELECT Sdept , AVG(grade) as "平均成績" 2> FROM student JOIN SC ON student.Sno = SC.Sno 3> GROUP BY Sdept; 4> GO Sdept D平均成績 --------------------D----------- 計算機系 D 73 數學系 D 89 信息系 D 55 // 1> SELECT Cno , COUNT(*) AS Total, AVG (grade), MAX(grade), MIN(grade) FROM student JOIN SC ON student.Sno = SC.Sno 2> WHERE Sdept ="計算機系" 3> GROUP BY Cno; 4> go Cno DTotal D D D ------D-----------D-----------D---D--- c01 D 2D 66D 90D 43 c02 D 1D NULLDNULDNUL c03 D 2D 78D 78D 78 c04 D 1D 78D 78D 78 (4 行受影響)
// 自鏈接 // 選擇跟李勇是一個系的其他同窗 1> SELECT s2.Sname, s2.Sdept FROM student s1 JOIN student s2 2> ON s1.Sdept = s2.Sdept 3> WHERE s1.Sname ="李勇" 4> AND s2.Sname!= "李勇"; 5> go Sname DSdept ----------D-------------------- 張錦傑 D計算機系
// 外鏈接 只限制一張表符合鏈接條件就行,不必定兩張表都知足 // 查詢學生的選課狀況,包括選課的和沒有選的(左內鏈接) 1> SELECT student.Sno, Sname, Cno, grade 2> FROM student LEFT OUTER JOIN SC 3> ON student.Sno = SC.Sno; 4> go Sno DSname DCno Dgrade --------D----------D------D----- 12122312D王大力 DNULL D NULL 13212311D張海 Dc01 D 89 13212311D張海 Dc02 D NULL 13212311D張海 Dc04 D 89 16101132D李勇 Dc01 D 43 16101132D李勇 Dc02 D NULL 16101132D李勇 Dc03 D 78 16101321D張錦傑 Dc01 D 90 16101321D張錦傑 Dc03 D 78 16101321D張錦傑 Dc04 D 78 16123211D吳斌 Dc01 D 12 16123211D吳斌 Dc02 D 23 16123211D吳斌 Dc03 D 65 16123211D吳斌 Dc05 D 78 16213322D王明 DNULL D NULL // 右鏈接 1> SELECT student.Sno, Sname, Cno, grade 2> FROM student RIGHT OUTER JOIN SC 3> ON student.Sno = SC.Sno; 4> go Sno DSname DCno Dgrade --------D----------D------D----- 13212311D張海 Dc01 D 89 13212311D張海 Dc02 D NULL 13212311D張海 Dc04 D 89 16101132D李勇 Dc01 D 43 16101132D李勇 Dc02 D NULL 16101132D李勇 Dc03 D 78 16101321D張錦傑 Dc01 D 90 16101321D張錦傑 Dc03 D 78 16101321D張錦傑 Dc04 D 78 16123211D吳斌 Dc01 D 12 16123211D吳斌 Dc02 D 23 16123211D吳斌 Dc03 D 65 16123211D吳斌 Dc05 D 78 (13 行受影響) // 查詢那些課程沒有被選 1> SELECT Cname FROM course C LEFT JOIN SC 2> ON c.Cno = SC.Cno 3> WHERE SC.Cno IS NULL; 4> GO Cname ---------- 數據結構 (1 行受影響) // 查詢並統計選課門數 1> SELECT S.Sno AS 學號 , COUNT(SC.Cno) AS 選課門數 2> FROM student S LEFT OUTER JOIN SC ON S.Sno = SC.Sno 3> GROUP BY S.Sno 4> ORDER BY COUNT(SC.Cno) DESC; 5> go 學號 D選課門數 --------D----------- 16123211D 4 13212311D 3 16101132D 3 16101321D 3 16213322D 0 12122312D 0
使用TOP限制結果集
// 倒敘顯示 前三個 1> SELECT TOP 3 Sname , Sage, Sdept 2> FROM student 3> ORDER BY Sage DESC; 4> GO Sname DSageDSdept ----------D----D-------------------- 張海 D 22D數學系 吳斌 D 22D信息系 王大力 D 21D數學系 // 包含並列 1> SELECT TOP 3 WITH TIES Sname, Sdept 2> FROM student 3> ORDER BY Sage DESC; 4> go Sname DSdept ----------D-------------------- 張海 D數學系 吳斌 D信息系 王明 D信息系 王大力 D數學系 (4 行受影響) // TOP 謂詞最好是於ORDER BY 配合使用 查詢選課人數最少的兩門課程(不包含沒有選課的人) 1> SELECT TOP 2 WITH TIES Cno, COUNT(*) 選課人數 2> FROM SC 3> GROUP BY Cno 4> ORDER BY COUNT(*) ASC; 5> GO Cno D選課人數 ------D----------- c05 D 1 c04 D 2
未完待續,小編正在急稿中~~