SQL Server 數據庫基本操作入門篇【7】

本文主講 數據更新(插入數據、修改數據、刪除數據)、空值的處理視圖,歡迎閱讀~


咳咳,先來概述一下數據操作:CRUD(增刪改查)
Create new records (即insert插入數據)
Retrieve existing records(即select查詢數據)
Update existing records(即update修改數據)
Delete existing records(即delete刪除數據)
(ps:這裏注意一下哈,create new records指的是插入數據,所用關鍵字是insert。create關鍵字是新建數據庫、模式、表、視圖用的,同樣的drop、alter也是用於表及其他的對象的,並不是用於直接操作數據)

一、插入數據

兩種插入數據方式:
· 插入元組
· 插入子查詢結果(可以一次插入多個元組 )

1. 插入元組

語句格式如下:

INSERT
INTO <表名> [(<屬性列1>[,<屬性列2 >)]   /*同樣的[]內的內容爲可選項,寫或不寫看情況*/
VALUES (<常量1> [,<常量2>]);

功能:新元組插入指定表

🌟來看例子:
將一個新學生元組(學號:201215128;姓名:陳冬;性別:男;所在系:IS;年齡:18歲)插入到Student表中:

INSERT
INTO  Student (Sno, Sname, Ssex, Sdept, Sage)
VALUES ('201215128', '陳冬', '男', 'IS', 18);   /*字符串常量用單引號(英文符號)括起來*/

在這裏插入圖片描述
👀咦,我這裏報錯了?原來是因爲我的Student表中已經有陳冬這個小夥子了,而且我給Sno設置了主碼約束,所以可見主碼(primary key)的強大作用:
①在table的邏輯上保證了不重複(這裏便是如此);②在使用的邏輯上保證了根據主碼,能取出唯一的一條記錄。
注意:這裏如果不寫屬性列(名)的話,VALUES裏的常量就必須按照表中的順序輸入!!)
在這裏插入圖片描述
在這裏插入圖片描述
可見,我這裏沒寫明屬性列,輸入常量時系別和年齡的順序和表中的不一致,所以提示:在將 varchar 值 'IS' 轉換成數據類型 smallint 時失敗。,所以如果想不寫屬性列(名)的話,就必須按照表中的順序輸入需要錄入的常量!!

🌟Another one: 插入一條選課記錄(‘201215135’, ‘1’):
需要注意的是,因爲Student的主碼Sno設置爲了SC的外碼,所以爲了參照完整性,Student表中要有學號爲201215135這個學生,否則會報錯!!

INSERT
INTO  SC(Sno, Cno)
VALUES ('201215135', '1');

在這裏插入圖片描述
可見RDBMS自動爲我們在新插入的記錄的Grade列賦了空值,但是如果沒有指出屬性列(名)的話,在VALUES裏要明確的在Grade列對應的位置寫上NULL!!

INSERT
INTO  SC
VALUES ('201215134', '1');

在這裏插入圖片描述
你看,這樣是不對的,在對應的位置加上NULL後:

INSERT
INTO  SC
VALUES ('201215134', '1', NULL);

在這裏插入圖片描述
在這裏插入圖片描述
成功執行✌~

2. 插入子查詢結果

語句格式:

INSERT 
INTO <表名>  [(<屬性列1> [,<屬性列2>)]
子查詢;

ps:這裏子查詢的結果即一個數據集合,且需是一個已經存在的表的數據的集合。
子查詢SELECT子句目標列必須與INTO子句匹配
① 值的個數
② 值的類型
🌟來看例子: 對每一個系,求學生的平均年齡,並把結果存入數據庫:
第一步:建表

CREATE TABLE Dept_age
		( Sdept  CHAR(15),                /*系名*/
		  Avg_age SMALLINT);          	/*學生平均年齡*/

第二步:插入數據

INSERT
INTO  Dept_age(Sdept, Avg_age)
SELECT Sdept, AVG(Sage)
FROM   Student
GROUP BY Sdept;

在這裏插入圖片描述
這裏是可以兩步一起執行的,如果想分開執行當然也闊以。用鼠標只選中第一個SQL語句點執行後就先執行了上面的SQL語句,建立好Dept_age表之後再執行下面的,不過既然可以兩句一起執行,就不必分步麻煩啦~(注意一步執行的話需要先建表,不然在插入語句裏找不到Dept_age表就執行不了)

❗❕❗ RDBMS在執行插入語句時會自動檢查所插元組是否破壞表上已定義的完整性規則:
①實體完整性
②參照完整性
③用戶定義的完整性
如上面的例子中的主碼約束和外碼約束示範。


二、修改數據

語句格式:

UPDATE <表名>
SET   <列名>=<表達式>[,<列名>=<表達式>][WHERE <條件>];

功能:
①修改指定表中滿足WHERE子句條件的元組
②SET子句給出<表達式>的值用於取代相應的屬性列
如果省略WHERE子句,表示要修改表中的所有元組

1. 修改某一個元組的值

🌟來看例子: 將學生201215121的年齡改爲22歲:

UPDATE Student
SET Sage = 22
WHERE Sno = '201215121'; 

SELECT * FROM Student;    /*打印出來對照一下*/

在這裏插入圖片描述

2. 修改多個元組的值

🌟來看例子: 所有學生的年齡增加1歲:

UPDATE Student
SET Sage = Sage + 1;

SELECT * FROM Student;    /*打印出來對照一下*/

在這裏插入圖片描述
與上個例子做比較,可見確實每人都增加了一歲,這種羣體範圍修改還挺好用嘿,一改改一羣😁

3. 帶子查詢的修改語句

🌟來看例子:計算機科學系全體學生的成績置零:
因爲這裏涉及到了兩個表Student和SCUPDATE只能作用於一個表,所以這裏需要先用子查詢得出計算機系的全體學生集合,然後將其學號Sno作爲WHERE子句的條件

UPDATE SC
SET Grade = 0
WHERE Sno IN
         (SELETE Sno
          FROM   Student
          WHERE  Sdept = 'CS');

SELECT Sno
FROM   Student
WHERE  Sdept = 'CS';  /*看一下計算機系的學生學號*/

SELECT * FROM SC;   /*打印出學生總表參照*/

在這裏插入圖片描述
❗❕❗RDBMS在執行修改語句時會檢查修改操作是否破壞表上已定義的完整性規則:
①實體完整性
②主碼不允許修改
③用戶定義的完整性
這裏需要注意一個地方就是在SQL Server中,在不破壞參照完整性的前提下是可以修改主碼的!!(具體參考我的另一篇博客:數據庫SQL語句UPDATE能否修改主碼


三、刪除數據

語句格式:

DELETE
FROM   <表名>
[WHERE <條件>];

功能: 刪除指定表中滿足WHERE子句條件的元組
WHERE子句:
· 指定要刪除的元組
· 缺省表示刪除表中的全部元組,表的定義仍在字典中(即只是把表裏的數據全刪了,表依然是存在的)

1. 刪除某一個元組的值

🌟來看例子: 刪除學號爲201215128的學生記錄:
你應該還有印象叭,學號爲201212128的學生就是剛剛例子裏的陳冬小夥子

DELETE
FROM  Student
WHERE Sno = '201215128';

SELECT * FROM Student  /*打印出來參照*/

在這裏插入圖片描述

2. 刪除多個元組的值

🌟來看例子: 刪除所有的學生選課記錄:

DELETE
FROM SC;

咳咳,這裏點了執行之後Student表裏的數據可就全沒了😅,一定要三思啊,所以建議大家先把Student表裏的數據備份起來,這裏我提前備份好了STUDENT數據庫,所以,我就放心刪除啦~
(ps:在SQL Server中如何進行數據庫的備份和還原可參考百度經驗:Sqlserver之數據庫的備份與還原
在這裏插入圖片描述
可見刪除後SC表依然是存在的,只是表裏的數據記錄全沒了
注意在刪除數據庫時,選擇【關閉現有連接】即可:
在這裏插入圖片描述

3. 帶子查詢的刪除語句

🌟來看例子: 刪除計算機科學系所有學生的選課記錄:
emmm,這裏我剛剛忘了先做這個實驗再刪整個SC表了,一激動就已經把SC表刪了哈哈哈哈,不過沒事,看我數據庫還原大法:
在這裏插入圖片描述

DELETE
FROM  SC
WHERE Sno IN
	       (SELECT Sno
            FROM   Student
            WHERE  Sdept = 'CS');
SELECT * FROM SC

SELECT Sno
FROM   Student
WHERE  Sdept = 'CS'

在這裏插入圖片描述


四、空值的處理

空值就是“不知道”或“不存在”或“無意義”的值。
一般有以下幾種情況:
①該屬性應該有一個值,但目前不知道它的具體值
該屬性不應該有值(比如某學生沒考試,那他的成績就不應該有值,填爲NULL,這和考了0分是不一樣的,0分可能是他考了但是沒寫或者隨便寫了點全錯了哈哈哈)
③由於某種原因不便於填寫

1. 空值的產生

空值是一個很特殊的值,含有不確定性。對關係運算帶來特殊的問題,需要做特殊的處理。

空值的產生
🌟來看例子: 向SC表中插入一個元組,學生號是”201215131”,課程號是”1”,成績爲空:

INSERT INTO SC(Sno, Cno, Grade)
VALUES ('201215131', '1', NULL);    /*該學生還沒有考試,取空值*/

INSERT INTO SC(Sno, Cno)
VALUES ('201215131', '1');        /*沒有賦值的屬性,其值爲空值*/

🌟Another one: 將Student表中學生號爲”201215222”的陳秋同學所屬的系改爲空值:

UPDATE Student
SET Sdept = NULL
WHERE Sno = '201215222';

在這裏插入圖片描述

2. 空值的判斷

判斷一個屬性的值是否爲空值,用IS NULL或IS NOT NULL來表示。

🌟來看例子: 從Student表中找出漏填了數據的學生信息:
!!這個很實用的哈,因爲在錄入信息時有時會漏填某個學生的信息,畢竟這是極少數,所以在學生數量很多很多的時候如果還去一個一個的檢查哪裏漏填了簡直要瘋掉了,這時候這個判斷語句就很有用,查出哪裏是空的漏填了,直接找到該學生的信息填上就ok

SELECT *
FROM   Student
WHERE  Sname IS NULL OR Ssex IS NULL OR Sage IS NULL OR Sdept IS NULL;

在這裏插入圖片描述

3. 空值的約束條件

屬性定義(或者域定義)中注意:
①有NOT NULL約束條件不能取空值
②加了UNIQUE限制的屬性不能取空值
碼屬性不能取空值(ps:表中的一列即爲一個屬性。表中的某個屬性組(即一列或多列),它可以唯一確定一個元組,則稱之爲,既然是唯一確定元組的,所以其屬性自然不能是空值啦)

4. 空值的算術運算、比較運算和邏輯運算

🌟來看例子: 找出選修1號課程的不及格的學生:

SELECT Sno
FROM   SC
WHERE  Grade < 60 AND Cno = '1';

ps:查詢結果不包括缺考的學生,因爲他們的Grade值爲NULL

🌟Another one: 選出選修1號課程不及格的學生以及缺考的學生:

SELECT Sno
FROM   SC
WHERE  Grade < 60 AND Cno = '1'
UNION
SELECT Sno
FROM   SC
WHERE  Grade IS NULL AND Cno = '1';

或者

SELECT Sno
FROM   SC
WHERE  Cno = '1' AND (Grade < 60 OR Grade IS NULL);  /*AND優先級高於OR,所以需要加上括號來提升優先級*/

在這裏插入圖片描述
兩種做法均可,不過在都容易理解的情況下,自然還是越簡潔越好啦,所以我果斷投第二種方法一票~


五、視圖

視圖的特點:
虛表,是從一個或幾個基本表(或視圖)導出的表
只存放視圖的定義不存放視圖對應的數據
基表中的數據發生變化,從視圖中查詢出的數據也隨之改變

1. 定義視圖(建立和刪除視圖)

· 建立視圖

語句格式:

CREATE VIEW <視圖名>  [(<列名>  [,<列名>])]
AS  <子查詢>
[WITH CHECK OPTION];

WITH CHECK OPTION:視圖進行更新操作自動添加子查詢中的條件(具體理解可看下面的例子~)

組成視圖的屬性列名:全部省略或全部指定
全部省略: 由子查詢中SELECT目標列中的諸字段組成
全部指定:(明確指定所有列名)
① 某個目標列聚集函數或列表達式(即自身不能作爲屬性名)
② 多表連接時選出了幾個同名列作爲視圖的字段
③ 需要在視圖中爲某個列啓用新的更合適的名字(在不同的應用場景下取合適的名字更方便理解~)

❗❕❗關係數據庫管理系統執行CREATE VIEW語句時只是把視圖定義存入數據字典,並不執行其中的SELECT語句(即只是先存起來,需要用的時候纔會執行)
在對視圖查詢時,按視圖的定義從基本表中將數據查出

🌟來看例子: 建立信息系學生的視圖:

CREATE VIEW IS_Student
AS 
SELECT Sno, Sname, Sage
FROM   Student
WHERE  Sdept = 'IS';

🌟Another one: 建立計算機系學生的視圖,並要求進行修改和插入操作時仍需保證該視圖只有計算機系的學生
(這裏即上面所說的:對視圖進行更新操作時自動添加子查詢中的條件,所以得用WITH CHECK OPTION

CREATE VIEW CS_Student
AS 
SELECT Sno, Sname, Sage
FROM   Student
WHERE  Sdept = 'CS'
WITH CHECK OPTION;

在這裏插入圖片描述
(ps:至於爲什麼標紅了CS_Student,一開始我的理解是因爲它是一個虛表,不是真實存在的表,所以DBMS提示我們這個對象無效,不過經過多次實踐發現:當新建了一個視圖或者表之後如果接着使用,系統就會給你標紅“無效”,但是是可以正常使用的,不過如果不想看到這些紅線的話,關閉SSMS重新打開就沒了,沒有強迫症的小夥伴可以不用在意此處標紅~)

❗❕❗注意:帶有WITH CHECK OPTION子句,所以對該視圖進行插入、修改和刪除操作(統稱爲更新操作)時,RDBMS會自動加上Sdept = 'CS'的條件

補充:若一個視圖是從單個基本表導出的,並且只是去掉了基本表的某些行和某些列,但保留了主碼,我們稱這類視圖爲行列子集視圖
比如:CS_Student視圖就是一個行列子集視圖。

👀 當然啦,視圖不僅僅只有上面的一種:
①基於多個基表的視圖

🌟來看例子: 建立計算機系選修了1號課程的學生的視圖(包括學號、姓名、成績):

CREATE VIEW CS_S1(Sno, Sname, Grade)
AS 
SELECT Student.Sno, Sname, Grade
FROM   Student, SC
WHERE  Sdept = 'CS' AND Student.Sno = SC.Sno AND SC.Cno = '1';

在這裏插入圖片描述
Student表上一個例子中打印了這裏就不打印啦(主要是屏幕佔不下了hhh)

②基於視圖的視圖

🌟來看例子: 建立計算機系選修了1號課程且成績在90分以上的學生的視圖:

CREATE VIEW CS_S2
AS
SELECT Sno, Sname, Grade
FROM   CS_S1
WHERE  Grade >= 90;

在這裏插入圖片描述
emm,因爲CS_S1視圖中就只有李勇小夥一個人,所以基於CS_S1建立的CS_S2還是他一枝獨秀

③帶表達式的視圖

🌟來看例子: 定義一個反映學生出生年份的視圖:

CREATE VIEW BT_S(Sno, Sname, Sbirth)
AS 
SELECT Sno, Sname, 2014-Sage
FROM  Student;

④分組視圖

🌟來看例子: 將學生的學號及平均成績定義爲一個視圖:

CREATE VIEW S_G(Sno, Gavg)
AS  
SELECT Sno, AVG(Grade)
FROM   SC
GROUP BY Sno;

🌟Another one: 將Student表中所有女生記錄定義爲一個視圖:

CREATE VIEW F_Student(F_Sno, name, sex, age, dept)
AS
SELECT *         /*沒有指定屬性列*/
FROM   Student
WHERE  Ssex = '女';

在這裏插入圖片描述
· 刪除視圖

語句格式:

DROP  VIEW  <視圖名>[CASCADE];

① 該語句從數據字典中刪除指定的視圖定義(注意只是會刪除定義哈,因爲視圖本身就是虛表,刪了對數據是沒有影響的)
② 如果該視圖上還導出了其他視圖,使用CASCADE級聯刪除語句,把該視圖和由它導出的所有視圖一起刪除
③ 刪除基表時,由該基表導出的所有視圖定義都必須顯式地使用DROP VIEW語句刪除(就是說刪了基本表,由它導出的視圖還是存在的,需要手動去一一刪除)
🌟來看例子: 刪除視圖BT_S和CS_S1:

DROP VIEW BT_S;	/*成功執行*/
DROP VIEW CS_S1;	/*拒絕執行*/

要刪除CS_S1,需使用級聯刪除CASCADE,同時刪除CS_S2:

DROP VIEW CS_S1 CASCADE;     

注意!!! 在SQL Server中是可以先單獨刪除CS_S1的:
在這裏插入圖片描述
然後再刪除CS_S2:
在這裏插入圖片描述

2. 查詢視圖

用戶角度:查詢視圖與查詢基本表相同(就像我們平時查車票查機票啥的,咱也不知道自己看的是視圖還是基本表)
RDBMS實現視圖查詢的方法視圖消解法(View Resolution)
· 進行有效性檢查
· 轉換成等價的對基本表的查詢
· 執行修正後的查詢
🌟來看例子: 在計算機系學生的視圖中找出年齡小於20歲的學生:

SELECT Sno, Sage
FROM   CS_Student
WHERE  Sage < 20;

視圖消解轉換後的查詢語句爲:
(就是直接變成查基本表了)

SELECT Sno, Sage       
FROM   Student
WHERE  Sdept = 'CS' AND Sage < 20;

在這裏插入圖片描述
不過視圖消解法也是有侷限的:有些情況下,視圖消解法不能生成正確的查詢

🌟來看例子: 在S_G視圖中查詢平均成績在90分以上的學生學號和平均成績:

SELECT *
FROM   S_G
WHERE  Gavg >= 90;

S_G視圖定義:

CREATE VIEW S_G (Sno, Gavg)
AS 
SELECT Sno, AVG(Grade)
FROM   SC
GROUP BY Sno;

🔥WHERE子句作用於基表或視圖,從中選擇滿足條件的元組
HAVING短語作用於組,是跟着GROUP BY用的,從中選擇滿足條件的組
錯誤:

SELECT Sno, AVG(Grade)
FROM   SC
WHERE  AVG(Grade) >= 90
GROUP BY Sno;

正確:

SELECT Sno, AVG(Grade)
FROM   SC
GROUP BY Sno
HAVING AVG(Grade) >= 90;

也可以用如下SQL語句完成(基於派生表的查詢)

SELECT *
FROM  (SELECT Sno, AVG(Grade)
       FROM   SC 
       GROUP BY Sno) AS S_G(Sno, Gavg)
WHERE Gavg >= 90;

3. 更新視圖

🌟直接看例子: 將計算機系學生視圖CS_Student中學號”201215122”的學生姓名改爲”劉辰”。

UPDATE CS_Student
SET  Sname= '劉辰'
WHERE Sno = '201215122';

轉換後的語句:

UPDATE Student
SET Sname = '劉辰'
WHERE Sno = '201215122' AND Sdept = 'CS';

🌟Another one: 向計算機系學生視圖CS_Student中插入一個新的學生記錄,其中學號爲”201215129”,姓名爲”趙新”,年齡爲20歲:

INSERT
INTO CS_Student
VALUES ('201215129', '趙新', 20);

轉換爲對基本表的更新:

INSERT
INTO Student(Sno, Sname, Sage, Sdept)
VALUES ('200215129 ', '趙新', 20, 'CS');

🌟Another one: 刪除計算機系學生視圖CS_Student中學號爲”201215129”的記錄:

DELETE
FROM  CS_Student
WHERE Sno = '201215129';

轉換爲對基本表的更新:

DELETE
FROM  Student
WHERE Sno = '201215129' AND Sdept = 'CS';

— — — — — — — — — — — — — — — — — — — —
更新視圖的限制: 一些視圖是不可更新的,因爲對這些視圖的更新不能唯一地有意義地轉換成對相應基本表的更新

比如:上面的一個例子中定義的視圖S_G(將學生的學號及平均成績定義爲一個視圖)爲不可更新視圖,其平均成績列來自於聚集函數AVG

UPDATE S_G
SET  Gavg = 90
WHERE Sno = '201215121';

因爲Gavg是由聚集函數產生的數據組成的列,並不存在對應的基本表中的實際數據

4. 視圖的作用

① 簡化用戶的操作(比較有針對性,比如你想看計算機系的學生直接看計算機系學生的視圖就可,不用再去學生總表裏查詢)
② 使用戶能以多種角度看待同一數據 (即不同的應用場景,如:學校裏食堂、教務處等對學生數據的看待角度是不同的)
③ 對重構數據庫提供了一定程度的邏輯獨立性
④ 對機密數據提供安全保護(只要機密的重要的數據不導出到視圖中,用戶通過視圖就看不到)
⑤ 適當的利用視圖可以更清晰的表達查詢


本文到這裏也就結束啦,這一期寫的好多啊,感謝你如此耐心地閱讀~😊,下一篇應該是要轉到【吐血整理】系列寫了,嘿嘿。
這裏是一個想把學習過程記錄成博客分享給大家的undergraduate,請多關照🙏
咱們下期 ~
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章