184.數據操縱語言DML

5.5 SQL的數據操縱功能算法

 

5.5.1 數據插入

  使用CREATE語句建立的數據表還只是一個「空殼」,表中沒有任何數據。利用SQL語言提供的INSERT語句能夠完成向數據表插入數據的任務。數據庫

INSERT語句的語法格式爲:express

INSERT [INTO] <table>[(<column1>[, <column2>…])]

VALUES(<value1>[, <value2>…]);

   table表示表名,value1, value2, …分別表示待插入的常量值,它們插入後造成同一條記錄上的各個字段值,且value1與字段column1對應,value2與字段column2對應,等。post

 

  關於插入語句INSERT,應注意如下幾點:spa

  <table>後面字段的順序和數量均可以是任意的(固然,字段的數量必須少於或等於表中定義字段的數量)。可是對給定順序的字段列表,VALUES子句中的常量值要分別按位置與字段列表中的字段相對應,並且數據類型也要一致。每一個常量值必須是具體的值,而不能沒有值。注意,「沒有值」不是空值(NULL),它們是兩個不一樣的概念。設計

  若是<table>後面沒有指定字段列表,那麼待插入的常量值的順序必須與表中定義字段的順序同樣。code

  除了在定義表時被設置爲NOT NULL之外,任何數據類型的字段均可以插入NULL(空值)。blog

 

【例5.25用INSERT語句將一個學號爲「20170201」、姓名爲「劉洋」、性別爲「女」、出生日期爲「1997-02-03」、專業爲「計算 機應用技術」、平均成績爲「98.5」、系別爲「計算機系」的學生記錄插入數據表student中。ci

根據以上信息,構造如下的記錄:('20170201','劉洋','女','1997-02-03','計算機應用技術',98.5,'計算機系')。該記錄中各份量值(常量值)的順序與表student中定義字段的順序相同,且數據類型也分別相同,所以能夠用不帶字段列表的INSERT語句來實現數據插入。代碼以下:開發

INSERT student(s_no,s_name,s_sex,s_birthday, s_speciality,s_avgrade,s_dept)

VALUES('20170201','劉洋','','1997-02-03','計算機應用技術',98.5,'計算機系');

該語句等價下列語句:

INSERT INTO student

VALUES('20170201','劉洋','','1997-02-03','計算機應用技術',98.5,'計算機系');

 

 

【例5.26用INSERT語句將一個學生記錄('20170202','王曉珂', 88.1) 插入數據表student中。

因爲該記錄並不包含全部的字段值,故在該INSERT語句中必須顯式指定字段列表(s_no, s_name, s_avgrade)。其實現代碼以下:

INSERT INTO student(s_no,s_name,s_avgrade)

VALUES('20170202','王曉珂', 88.1); 

因爲字段的順序能夠是任意的(但插入值要與字段對應),因此該語句等價與下列的INSERT語句:

INSERT  INTO student(s_name, s_avgrade, s_no)

VALUES('王曉珂', 88.1, '20170202');

 

 

  注意:主鍵字段的值不能重複,也不能爲空值(NULL);

  被設爲NOT NULL的字段的插入值也不能爲空值。

  此外,對於其餘沒有被插入的字段(如字段s_sex, s_birthday等),若是在定義表時設置了默認值,則這些字段會自動填上默認值,不然自動填上空值。

  在執行上述語句後,新插入的記錄在字段s_speciality和s_dept上分別取默認值「計算機軟件與理論」和「計算機科學系」,在字段s_sex和s_birthday,上都取空值(NULL)。

  

 

  另外一種插入數據的方法是在INSERT語句中嵌入子查詢,以子查詢的返回結果集做爲插入的數據。這樣能夠實現數據的批量插入,這在許多地方都有應用。但要求子查詢的返回結果集和被插入數據的數據表在結果上要一致,不然沒法完成插入操做。

  例5.27】  查詢表student中學生的學號、姓名、專業、平均成績和系別,並將查詢結果輸入到另外一個數據表中。

首先要建立一個包含學號(s_no)、姓名(s_name)、專業(s_speciality)、平均成績(s_avgrade)和系別(s_dept)的數據表student2,相應CREATE語句以下:

CREATE TABLE student2(

s_no char(8) PRIMARY KEY,

s_name char(8) NOT NULL,

s_speciality varchar(50) DEFAULT  '計算機軟件與理論',

s_avgrade numeric(3,1) CHECK(s_avgrade >= 0 AND s_avgrade <= 100),

s_dept varchar(50) DEFAULT  '計算機科學系'

); 

建立以下的查詢:

SELECT s_no, s_name, s_speciality, s_avgrade, s_dept

FROM student;

 

 

  能夠看出,上述查詢返回的結果集在結構上與表student2是一致的。因此,該查詢能夠做爲子查詢嵌入到用於向表student1插入數據的INSERT語句中,從而實現將查詢結果插入到表student2中的目的。相應的SQL語句以下:

INSERT INTO student2(s_no, s_name, s_speciality, s_avgrade, s_dept)

(SELECT s_no, s_name, s_speciality, s_avgrade, s_dept

FROM student); 

 

 

       注意:上述INSERT語句中並沒有關鍵字VALUES

 

 

 

5.5.2 數據更新

  在數據輸入到數據表之後,或者是因爲錯誤的輸入,或者是因爲應用環境和時間的變化等緣由,都有可能須要對錶中的數據進行修改。在SQL語句中,UPDATE語句提供了數據修改功能。其語法格式以下:

UPDATE <table>

SET <column1> = <value1>[,<column2> = <value2>…]

[WHERE <condition_expression>]

  <table>表示要修改數據的表;關鍵字SET後面的column1, column2, …表示要修改的字段,value1, value2, …對應字段修改後的新值;condition_expression爲一邏輯表達式,此處表示修改條件。若是UPDATE語句不包含WHERE子句,則表示無條件對錶中全部記錄都進行修改(無條件修改);若是包含了WHERE子句,那麼只有對知足修改條件的記錄進行修改(有條件修改)。

 

 

【例5.28將全部學生的平均成績都減5分。

這是一個無條件修改,相應語句以下:

UPDATE student

SET s_avgrade = s_avgrade - 5;

 

【例5.29將全部女學生的平均成績都加上其原來分數的0.5%。

這是一個有條件修改,相應語句以下:

UPDATE student

SET s_avgrade = s_avgrade + s_avgrade*0.005

WHERE s_sex = '';

 

  在項目開發實踐中,常常遇到這樣的操做:用一個表去更新另一個表。在這種更新操做中,有一些「技巧」須要注意。根據1.5.2節的分析,兩個表(實體)之間的聯繫主要有三種狀況:(1:1)、(1:n)和(m:n)。若是兩個表之間的聯繫是(m:n),則不宜用任何一個表去更新另一個表;若是它們的聯繫是(1:n),則能夠用「1」對應的表去更新「n」對應的表;若是它們的聯繫是(1:1),則能夠用其中任何一個表去更新另一個表。

 

 

【例5.30用學分表credit去更新課程信息表SC2。

從SQL語法上看,用一個表去更新另外一個表,相應語句並不複雜。但要保證其語義上的正確性,這並不容易。咱們考慮這樣的例子:學分表credit保存了每門課程的課程名和學分,課程信息表SC2則保存學生選修的課程信息,包括學號、課程名、成績和學分。表credit和表SC2的定義代碼以下:

CREATE TABLE credit(  -- 表credit

c_name varchar(20)  PRIMARY KEY,

c_credit    int

);

CREATE TABLE SC2(  -- 表SC2  

s_no char(8),

c_name varchar(20),

c_gradenumeric(3,1)       CHECK(c_grade >= 0 AND c_grade <= 100),

c_credit   int,

PRIMARY KEY(s_no, c_name)       --將(s_no, c_name)設爲主鍵

);

而後在這兩個表中添加相關數據:

INSERT credit VALUES('英語',3);

INSERT credit VALUES('數據庫原理',4);

INSERT credit VALUES('算法設計與分析',2);

 

INSERT SC2(s_no,c_name,c_grade) VALUES('20170201','英語',80.2);

INSERT SC2(s_no,c_name,c_grade) VALUES('20170201','數據庫原理',70.0);

INSERT SC2(s_no,c_name,c_grade) VALUES('20170201','算法設計與分析',92.4);

INSERT SC2(s_no,c_name,c_grade) VALUES('20170202','英語',81.9);

INSERT SC2(s_no,c_name,c_grade) VALUES('20170202','算法設計與分析',85.2);

INSERT SC2(s_no,c_name,c_grade) VALUES('20170203','多媒體技術',68.1);

注意,表SC2中的學分字段c_credit未添加任何數據。能夠看到,表credit和表SC2之間的聯繫是基於課程名稱c_name的(1:n)聯繫(「一對多」聯繫),即表credit中的一條數據可能對應着表SC2中的多條數據,所以能夠用「1」對應的表c_credit去更新「n」對應的表SC2。具體地,能夠用表credit中的學分字段c_credit去更新表SC2中的學分字段c_credit,相應UPDATE語句以下:

UPDATE  SC2

SET SC2.c_credit = credit.c_credit

FROM SC2

JOIN credit

ON SC2.c_name = credit.c_name

執行上述語句後,表SC2中的內容以下:

s_no c_namec_grade                c_credit

---------------------------------------------------------------------------------------------------

20170201數據庫原理                      70.04

20170201算法設計與分析92.42

20170201英語80.23

20170202算法設計與分析85.22

20170202英語81.93

20170203多媒體技術     68.1NULL

能夠看到,更新結果是正確的。

須要注意的是,在「一對多」的兩個表中,必須保證是用「1」表去更新「n」表,不然極爲可能出現問題。

  說明: 若是用表SC2去更新表credit,則會容易出現不一致性等問題。請讀者考慮這個問題。

 

 

【例5.30假設表student中的平均成績(s_avgrade)是由表SC中的課程成績(c_grade)平均獲得的,請經過查詢表SC的方法來更新表student中的s_avgrade字段值,使之知足上述假設。    
        對於「劉洋」的平均成績,它是《英語》、《數據庫原理》和《算法設計與分析》這三門課程成績的平均值(由於表SC顯示「劉洋」選修了這三門課程),結果應該是(70.0+92.4+80.2)/3=80.9。對於其餘學生的平均成績亦可類推。

         可是用SQL語言求出各個學生的平均成績並填到表student中,這不是一件很容易的事情。咱們經過建立一個用於存放中間結果的數據表的方法來解決這個問題,相應的SQL語句及其說明以下:

(1) 建立一個用於存放中間結果的數據表tmp_table

CREATE TABLE tmp_table(

s_no char(8),  

s_avgrade numeric(3,1)  

);

(2)經過按學號分組的方法求各個學生的平均成績,並將其學號和平均成績存放到表tmp_table中

INSERT INTO tmp_table(s_no,s_avgrade)

(SELECT  s_no, AVG(c_grade) --c_grade

FROM SC

GROUP BY s_no);

 

表student和表tmp_table的聯繫是基於字段s_no的(1:1)聯繫。所以,咱們能夠用表tmp_table中的平均成績字段s_avgrade去更新表student中的平均成績字段s_avgrade:

UPDATE student

SET s_avgrade = b.s_avgrade

FROM  student as a

JOIN tmp_table as b

ON a.s_no = b.s_no

DROP TABLE tmp_table; -- 刪除臨時數據表

通過一次性執行以上代碼後便可計算出各位學生的平均成績。

 

 

5.5.3 數據刪除

  通常來講,數據也有個生成、發展和淘汰的過程。隨着時間的推移,在通過長期使用後有些數據必須予以淘汰。對數據庫來講,淘汰就意味着刪除。在SQL語言中,DELETE  語句提供了數據刪除功能,其通常語法格式以下:

DELETE   

FROM <table>

[WHERE <condition_expression>];

    table表示要刪除數據的表,condition_expression亦爲一邏輯表達式,此處表示刪除條件。若是DELETE語句不包含WHERE子句,則表示無條件刪除表<table>中全部的數據(無條件刪除);若是包含了WHERE子句,那麼只刪除那些知足刪除條件的記錄(有條件刪除)。

 

【例5.31刪除表student中的全部數據。

這是一個無條件刪除,其實現語句以下:

DELETE FROM student;

 


【例5.32刪除表student中沒有選修任何課程的學生。

這是一個有條件刪除。因爲學生的選課信息保存在表SC中,因此這個刪除操做要涉及到兩個數據表。一個直觀的想法是,只要一個學生的學號沒有在表SC中出現,則代表該學生沒有選修課程,應予以刪除。所以,很容易想到使用子查詢來實現:

DELETE   

FROM student

WHERE s_no NOT IN (

SELECT s_no

FROM SC);

 

 

 

相關文章
相關標籤/搜索