SQL Server 學習 SQL 語句 ( 二 )

SQL 語法總結

完整性約束數據庫

  • NOT NULL 列值非空
  • DEFAULT 列的默認值
  • UNIQUE 限制列取值不能重複
  • CHECK 限制列的取值範圍
  • PRIMARY KEY 主鍵
  • FOREIGN KEY 外碼

定義主碼約束數據結構

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

查詢知足條件的元組

  • WHERE 用法
  • 經常使用的查詢條件
查詢條件 謂詞
比較 = > < <= >= != 以及 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. _ 下劃線, 匹配任意一個字符
  2. % 匹配0或者多個字符
  3. [] 匹配[]中的任意一個字符
  4. [^] 不匹配[]中的任意一個字符
// 匹配姓張的人

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;
  • 多重條件查找

就是 ANDOR

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. COUNT(*) 統計表中元組的個數
  2. COUNT (DISTINCT sno) 統計本列非空值個數
  3. SUM (列名) 計算列的總和
  4. AVG (列名) 計算列的平均值
  5. MAX (列名) 列的最大值
  6. MIN (列名) 列的最小值
// 元組總個數
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

未完待續,小編正在急稿中~~
相關文章
相關標籤/搜索