主頁 > 資料庫 > SQL 如何插入、洗掉和更新資料

SQL 如何插入、洗掉和更新資料

2022-07-14 10:05:17 資料庫

目錄
  • 一、資料的插入(INSERT 陳述句的使用方法)
    • 1.1 什么是 INSERT
    • 1.2 INSERT 陳述句的基本語法
    • 1.3 列清單的省略
    • 1.4 插入 NULL
    • 1.5 插入默認值
    • 1.6 從其他表中復制資料
  • 二、資料的洗掉(DELETE 陳述句的使用方法)
    • 2.1 DROP TABLE 陳述句和 DELETE 陳述句
    • 2.2 DELETE 陳述句的基本語法
    • 2.3 指定洗掉物件的 DELETE 陳述句(搜索型 DELETE)
  • 三、資料的更新(UPDATE 陳述句的使用方法)
    • 3.1 UPDATE 陳述句的基本語法
    • 3.2 指定條件的 UPDATE 陳述句(搜索型 UPDATE)
    • 3.3 使用 NULL 進行更新
    • 3.4 多列更新

本文將會給大家介紹 DBMS 中用來更新表中資料的方法,SQL 資料的更新處理大體可以分為插入(INSERT)、洗掉(DELETE)和更新(UPDATE)三類,本文將會對這三類更新方法進行詳細介紹,

一、資料的插入(INSERT 陳述句的使用方法)

本節重點

  • 使用 INSERT 陳述句可以向表中插入資料(行),原則上,INSERT 陳述句每次執行一行資料的插入,

  • 將列名和值用逗號隔開,分別括在 () 內,這種形式稱為清單,

  • 對表中所有列進行 INSERT 操作時可以省略表名后的列清單,

  • 插入 NULL 時需要在 VALUES 子句的值清單中寫入 NULL

  • 可以為表中的列設定默認值(初始值),默認值可以通過在 CREATE TABLE 陳述句中為列設定 DEFAULT 約束來設定,

  • 插入默認值可以通過兩種方式實作,即在 INSERT 陳述句的 VALUES 子句中指定 DEFAULT 關鍵字(顯式方法),或省略列清單(隱式方法),

  • 使用 INSERT…SELECT 可以從其他表中復制資料,

1.1 什么是 INSERT

SQL 如何對表進行創建、更新和洗掉操作 給大家介紹了用來創建表的 CREATE TABLE 陳述句,通過 CREATE TABLE 陳述句創建出來的表,可以被認為是一個空空如也的箱子,

只有把資料裝入到這個箱子后,它才能稱為資料庫,用來裝入資料的 SQL 就是 INSERT(插入)(圖 1),

INSERT(插入)的流程

圖 1 INSERT(插入)的流程

本節將會和大家一起學習 INSERT 陳述句,

要學習 INSERT 陳述句,我們得首先創建一個名為 ProductIns 的表,請大家執行代碼清單 1 中的 CREATE TABLE 陳述句,

該表除了為 sale_price 列(銷售單價)設定了 DEFAULT 0 的約束之外,其余內容與之前使用的 Product(商品)表完全相同,

DEFAULT 0 的含義將會在隨后進行介紹,大家暫時可以忽略,

代碼清單 1 創建 ProductIns 表的 CREATE TABLE 陳述句

CREATE TABLE ProductIns
(product_id      CHAR(4)      NOT NULL,
 product_name    VARCHAR(100) NOT NULL,
 product_type    VARCHAR(32)  NOT NULL,
 sale_price      INTEGER      DEFAULT 0,
 purchase_price  INTEGER      ,
 regist_date     DATE         ,
 PRIMARY KEY (product_id));

如前所述,這里僅僅是創建出了一個表,并沒有插入資料,接下來,我們就向 ProductIns 表中插入資料,

1.2 INSERT 陳述句的基本語法

SQL 如何對表進行創建、更新和洗掉操作 中講到向 CREATE TABLE 陳述句創建出的 Product 表中插入資料的 SQL 陳述句時,曾介紹過 INSERT 陳述句的使用示例,但當時的目的只是為學習 SELECT 陳述句準備所需的資料,并沒有詳細介紹其語法,

下面就讓我們來介紹一下 INSERT 陳述句的語法結構,

INSERT 陳述句的基本語法如下所示,

語法 1 INSERT 陳述句

INSERT INTO <表名> (列1, 列2, 列3, ……) VALUES (值1, 值2, 值3, ……);

例如,我們要向 ProductIns 表中插入一行資料,各列的值如下所示,

product_id(商品編號) product_name(商品名稱) product_type(商品種類) sale_price(銷售單價) purchase_price(進貨單價) regist_date(登記日期)
0001 T 恤衫 衣服 1000 500 2009-09-20

此時使用的 INSERT 陳述句可參見代碼清單 2,

代碼清單 2 向表中插入一行資料

INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, purchase_price, regist_date)
VALUES ('0001', 'T恤衫', '衣服', 1000, 500, '2009-09-20');

由于 product_id 列(商品編號)和 product_name 列(商品名稱)是字符型,所以插入的資料需要像 '0001' 這樣用單引號括起來,日期型的 regist_date(登記日期)列也是如此 [1]

將列名和值用逗號隔開,分別括在 () 內,這種形式稱為清單,代碼清單 2 中的 INSERT 陳述句包含如下兩個清單,

A:列清單(product_id, product_name, product_type, sale_price, purchase_price, regist_date)

B:值清單('0001', 'T恤衫', '衣服', 1000, 500,'2009-09-20')

當然,表名后面的列清單和 VALUES 子句中的值清單的列數必須保持一致,如下所示,列數不一致時會出錯,無法插入資料 [2]

-- VALUES子句中的值清單缺少一列
INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, purchase_price, regist_date)
VALUES ('0001', 'T恤衫', '衣服', 1000, 500);

此外,原則上,執行一次 INSERT 陳述句會插入一行資料 [3],因此,插入多行時,通常需要回圈執行相應次數的 INSERT 陳述句,

法則 1

原則上,執行一次 INSERT 陳述句會插入一行資料,

專欄

多行 INSERT

法則 1 中介紹了“執行一次 INSERT 陳述句會插入一行資料”的原則,

雖然在大多數情況下該原則都是正確的,但它也僅僅是原則而已,其實很多 RDBMS 都支持一次插入多行資料,這樣的功能稱為多行 INSERT(multi row INSERT),

其語法請參見代碼清單 A,將多條 VALUES 子句通過逗號進行分隔排列,

代碼清單 A 通常的 INSERT 和多行 INSERT

-- 通常的INSERT
INSERT INTO ProductIns VALUES ('0002', '打孔器', '辦公用品', 500, 320, '2009-09-11');
INSERT INTO ProductIns VALUES ('0003', '運動T恤', '衣服', 4000, 2800, NULL);
INSERT INTO ProductIns VALUES ('0004', '菜刀', '廚房用具', 3000, 2800, '2009-09-20');

-- 多行INSERT (Oracle以外)
INSERT INTO ProductIns VALUES ('0002', '打孔器', '辦公用品', 500, 320, '2009-09-11'),
('0003', '運動T恤', '衣服', 4000, 2800, NULL),
('0004', '菜刀', '廚房用具', 3000, 2800, '2009-09-20');

該語法很容易理解,并且減少了書寫陳述句的數量,非常方便,但是,使用該語法時請注意以下幾點,

首先,INSERT 陳述句的書寫內容及插入的資料是否正確,若不正確會發生 INSERT 錯誤,但是由于是多行插入,和特定的單一行插入相比,想要找出到底是哪行哪個地方出錯了,就變得十分困難,

其次,多行 INSERT 的語法并不適用于所有的 RDBMS,該語法適用于 DB2、SQL、SQL Server、PostgreSQL 和 MySQL,但不適用于 Oracle

特定的 SQL

Oracle 使用如下語法來巧妙地完成多行 INSERT 操作,

-- Oracle中的多行INSERT
INSERT ALL INTO ProductIns VALUES ('0002', '打孔器', '辦公用品', 500, 320, '2009-09-11')
          INTO ProductIns VALUES ('0003', '運動T恤', '衣服', 4000, 2800, NULL)
          INTO ProductIns VALUES ('0004', '菜刀', '廚房用具', 3000, 2800, '2009-09-20')
SELECT * FROM DUAL;

DUAL 是 Oracle 特有(安裝時的必選項)的一種臨時表,因此“SELECT * FROM DUAL”部分也只是臨時性的,并沒有實際意義,

在書寫沒有參照表的 SELECT 陳述句時,寫在 FROM 子句中的表,它并沒有實際意義,也不保存任何資料,同時也不能作為 INSERTUPDATE 的物件,

1.3 列清單的省略

對表進行全列 INSERT 時,可以省略表名后的列清單,這時 VALUES 子句的值會默認按照從左到右的順序賦給每一列,因此,代碼清單 3 中的兩個 INSERT 陳述句會插入同樣的資料,

代碼清單 3 省略列清單

-- 包含列清單
INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, purchase_price, regist_date)
VALUES ('0005', '高壓鍋', '廚房用具', 6800, 5000, '2009-01-15');

-- 省略列清單
INSERT INTO ProductIns VALUES ('0005', '高壓鍋', '廚房用具', 6800, 5000, '2009-01-15');

1.4 插入 NULL

INSERT 陳述句中想給某一列賦予 NULL 值時,可以直接在 VALUES 子句的值清單中寫入 NULL

例如,要向 purchase_price 列(進貨單價)中插入 NULL,就可以使用代碼清單 4 中的 INSERT 陳述句,

代碼清單 4 向 purchase_price 列中插入 NULL

INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, purchase_price, regist_date)
VALUES ('0006', '叉子', '廚房用具', 500, NULL, '2009-09-20');

但是,想要插入 NULL 的列一定不能設定 NOT NULL 約束,向設定了 NOT NULL 約束的列中插入 NULL 時,INSERT 陳述句會出錯,導致資料插入失敗,

插入失敗指的是希望通過 INSERT 陳述句插入的資料無法正常插入到表中,但之前已經插入的資料并不會被破壞 [4]

1.5 插入默認值

我們還可以向表中插入默認值(初始值),可以通過在創建表的 CREATE TABLE 陳述句中設定 DEFAULT 約束來設定默認值,

本文開頭創建的 ProductIns 表的定義部分請參見代碼清單 5,其中 DEFAULT 0 就是設定 DEFAULT 約束的部分,像這樣,我們可以通過“DEFAULT <默認值>”的形式來設定默認值,

代碼清單 5 創建 ProductIns 表的 CREATE TABLE 陳述句(節選)

CREATE TABLE ProductIns
(product_id     CHAR(4)  NOT NULL,
         (略)
 sale_price      INTEGER  DEFAULT 0, -- 銷售單價的默認值設定為0;
         (略)
 PRIMARY KEY (product_id));

如果在創建表的同時設定了默認值,就可以在 INSERT 陳述句中自動為列賦值了,默認值的使用方法通常有顯式和隱式兩種,

  • 通過顯式方法插入默認值

    VALUES 子句中指定 DEFAULT 關鍵字(代碼清單 6),

    代碼清單 6 通過顯式方法設定默認值

    INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, purchase_price, regist_date)
    VALUES ('0007', '擦菜板', '廚房用具', DEFAULT, 790, '2009-04-28');
    

    這樣一來,RDBMS 就會在插入記錄時自動把默認值賦給對應的列,

    我們可以使用 SELECT 陳述句來確認通過 INSERT 陳述句插入的資料行,

    -- 確認插入的資料行;
    SELECT * FROM ProductIns WHERE product_id = '0007';
    

    因為 sale_price 列(銷售單價)的默認值是 0,所以 sale_price 列被賦予了值 0

    執行結果:

    product_id | product_name | product_type | sale_price | purchase_price | regist_date
    -----------+--------------+--------------+------------+----------------+----------
    0007      | 擦菜板       | 廚房用具     |          0 |            790  | 2008-04-28
    
  • 通過隱式方法插入默認值

    插入默認值時也可以不使用 DEFAULT 關鍵字,只要在列清單和 VALUES 中省略設定了默認值的列就可以了,

    我們可以像代碼清單 7 那樣,從 INSERT 陳述句中洗掉 sale_price 列(銷售單價),

    代碼清單 7 通過隱式方法設定默認值

    代碼清單 7 通過隱式方法設定默認值

    這樣也可以給 sale_price 賦上默認值 0

    那么在實際使用中哪種方法更好呢?筆者建議大家使用顯式的方法,因為這樣可以一目了然地知道 sale_price 列使用了默認值,SQL 陳述句的含義也更加容易理解,

    說到省略列名,還有一點要說明一下,如果省略了沒有設定默認值的列,該列的值就會被設定為 NULL

    因此,如果省略的是設定了 NOT NULL 約束的列,INSERT 陳述句就會出錯(代碼清單 8),請大家一定要注意,

    代碼清單 8 未設定默認值的情況

    -- 省略purchase_price列(無約束):會賦予“NULL”
    INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, regist_date)
    VALUES ('0008', '圓珠筆', '辦公用品', 100, '2009-11-11');
    
    -- 省略product_name列(設定了NOT NULL約束):錯誤!
    INSERT INTO ProductIns (product_id, product_type, sale_price,purchase_price, regist_date)
    VALUES ('0009', '辦公用品', 1000, 500, '2009-12-12');
    

    法則 2

    省略 INSERT 陳述句中的列名,就會自動設定為該列的默認值(沒有默認值時會設定為 NULL),

1.6 從其他表中復制資料

要插入資料,除了使用 VALUES 子句指定具體的資料之外,還可以從其他表中復制資料,下面我們就來學習如何從一張表中選取資料,復制到另外一張表中,

要學習該方法,我們首先得創建一張表(代碼清單 9),

代碼清單 9 創建 ProductCopy 表的 CREATE TABLE 陳述句

-- 用來插入資料的商品復制表
CREATE TABLE ProductCopy
(product_id      CHAR(4)      NOT NULL,
 product_name    VARCHAR(100) NOT NULL,
 product_type    VARCHAR(32)  NOT NULL,
 sale_price      INTEGER      ,
 purchase_price  INTEGER      ,
 regist_date     DATE         ,
 PRIMARY KEY (product_id));

ProductCopy(商品復制)表的結構與之前使用的 Product(商品)表完全一樣,只是更改了一下表名而已,

接下來,就讓我們趕快嘗試一下將 Product 表中的資料插入到 ProductCopy 表中吧,代碼清單 10 中的陳述句可以將查詢的結果直接插入到表中,

代碼清單 10 INSERT ... SELECT 陳述句

-- 將商品表中的資料復制到商品復制表中
INSERT INTO ProductCopy (product_id, product_name, product_type, sale_price, purchase_price, regist_date)
SELECT product_id, product_name, product_type, sale_price, purchase_price, regist_date
  FROM Product;

執行該 INSERT … SELECT 陳述句時,如果原來 Product 表中有 8 行資料,那么 ProductCopy 表中也會插入完全相同的 8 行資料,

當然,Product 表中的原有資料不會發生改變,因此,INSERT … SELECT 陳述句可以在需要進行資料備份時使用(圖 2),

INSERT ... SELECT 陳述句

圖 2 INSERT … SELECT 陳述句

  • 多種多樣的 SELECT 陳述句

    INSERT 陳述句中的 SELECT 陳述句,也可以使用 WHERE 子句或者 GROUP BY 子句等,

    目前為止學到的各種 SELECT 陳述句也都可以使用 [5],對在關聯表之間存取資料來說,這是非常方便的功能,

    接下來我們嘗試一下使用包含 GROUP BY 子句的 SELECT 陳述句進行插入,代碼清單 11 中的陳述句創建了一個用來插入資料的表,

    代碼清單 11 創建 ProductType 表的 CREATE TABLE 陳述句

    -- 根據商品種類進行匯總的表;
    CREATE TABLE ProductType
    (product_type       VARCHAR(32)     NOT NULL,
    sum_sale_price     INTEGER         ,
    sum_purchase_price INTEGER         ,
    PRIMARY KEY (product_type));
    

    該表是用來存盤根據商品種類(product_type)計算出的銷售單價合計值以及進貨單價合計值的表,

    下面就讓我們使用代碼清單 12 中的 INSERT ... SELECT 陳述句,從 Product 表中選取出資料插入到這張表中吧,

    代碼清單 12 插入其他表中資料合計值的 INSERT ... SELECT 陳述句

    INSERT INTO ProductType (product_type, sum_sale_price, sum_purchase_price)
    SELECT product_type, SUM(sale_price), SUM(purchase_price)
    FROM Product
    GROUP BY product_type;
    

    通過 SELECT 陳述句對插入結果進行確認,我們發現 ProductType 表中插入了以下 3 行資料,

    -- 確認插入的資料行
    SELECT * FROM ProductType;
    

    執行結果:

    product_type | sum_sale_price  | sum_purchase_price
    --------------+-----------------+--------------------
    衣服         |            5000 |               3300
    辦公用品     |             600 |                320
    廚房用具     |           11180 |               8590
    

    法則 3

    INSERT 陳述句的 SELECT 陳述句中,可以使用 WHERE 子句或者 GROUP BY 子句等任何 SQL 語法(但使用 ORDER BY 子句并不會產生任何效果),

二、資料的洗掉(DELETE 陳述句的使用方法)

本節重點

如果想將整個表全部洗掉,可以使用 DROP TABLE 陳述句,如果只想洗掉表中全部資料,需使用 DELETE 陳述句,

如果想洗掉部分資料行,只需在 WHERE 子句中書寫物件資料的條件即可,通過 WHERE 子句指定洗掉物件的 DELETE 陳述句稱為搜索型 DELETE 陳述句,

2.1 DROP TABLE 陳述句和 DELETE 陳述句

上一節我們學習了插入資料的方法,本節我們來學習如何洗掉資料,洗掉資料的方法大體可以分為以下兩種,

DROP TABLE 陳述句可以將表完全洗掉

DELETE 陳述句會留下表(容器),而洗掉表中的全部資料

① 中的 DROP TABLE 陳述句我們已經在 SQL 如何對表進行創建、更新和洗掉操作 中學過了,此處再簡單回顧一下,

DROP TABLE 陳述句會完全洗掉整張表,因此洗掉之后再想插入資料,就必須使用 CREATE TABLE 陳述句重新創建一張表,

反之,② 中的 DELETE 陳述句在洗掉資料(行)的同時會保留資料表,因此可以通過 INSERT 陳述句再次向表中插入資料,

本節所要介紹的洗掉資料,指的就是只洗掉資料的 DELETE 陳述句,

此外,我們在 SQL 如何對表進行創建、更新和洗掉操作 中也提到過,不管使用哪種方法,洗掉資料時都要慎重,一旦誤刪,想要恢復資料就會變得十分困難,

2.2 DELETE 陳述句的基本語法

DELETE 陳述句的基本語法如下所示,十分簡單,

語法 2 保留資料表,僅洗掉全部資料行的 DELETE 陳述句

DELETE FROM <表名>;

執行使用該基本語法的 DELETE 陳述句,就可以洗掉指定的表中的全部資料行了,因此,想要洗掉 Product 表中全部資料行,就可以參照代碼清單 13 來書寫 DELETE 陳述句,

代碼清單 13 清空 Product 表

DELETE FROM Product;

如果陳述句中忘了寫 FROM,而是寫成了“DELETE <表名>”,或者寫了多余的列名,都會出錯,無法正常執行,請大家特別注意,

前者無法正常執行的原因是洗掉物件不是表,而是表中的資料行(記錄),這樣想的話就很容易理解了吧 [6]

后者錯誤的原因也是如此,因為 DELETE 陳述句的物件是行而不是列,所以 DELETE 陳述句無法只洗掉部分列的資料,

因此,在 DELETE 陳述句中指定列名是錯誤的,當然,使用星號的寫法(DELETE * FROM Product;)也是不對的,同樣會出錯,

法則 4

DELETE 陳述句的洗掉物件并不是表或者列,而是記錄(行),

2.3 指定洗掉物件的 DELETE 陳述句(搜索型 DELETE)

想要洗掉部分資料行時,可以像 SELECT 陳述句那樣使用 WHERE 子句指定洗掉條件,這種指定了洗掉物件的 DELETE 陳述句稱為搜索型 DELETE [7]

搜索型 DELETE 的語法如下所示,

語法 3 洗掉部分資料行的搜索型 DELETE

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

下面讓我們以 Product(商品)表為例,來具體研究一下如何進行資料洗掉(表 1),

表 1 Product 表

product_id(商品編號) product_name(商品名稱) product_type(商品種類) sale_price(銷售單價) purchase_price(進貨單價) regist_date(登記日期)
0001 T 恤衫 衣服 1000 500 2009-09-20
0002 打孔器 辦公用品 500 320 2009-09-11
0003 運動 T 恤 衣服 4000 2800
0004 菜刀 廚房用具 3000 2800 2009-09-20
0005 高壓鍋 廚房用具 6800 5000 2009-01-15
0006 叉子 廚房用具 500 2009-09-20
0007 擦菜板 廚房用具 880 790 2008-04-28
0008 圓珠筆 辦公用品 100 2009-11-11

假設我們要洗掉銷售單價(sale_price)大于等于 4000 元的資料(代碼清單 14),上述表中滿足該條件的是“運動 T 恤”和“高壓鍋”,

代碼清單 14 洗掉銷售單價(sale_price)大于等于 4000 元的資料

DELETE FROM Product
 WHERE sale_price >= 4000;

WHERE 子句的書寫方式與此前介紹的 SELECT 陳述句完全一樣,

通過使用 SELECT 陳述句確認,表中的資料被洗掉了 2 行,只剩下 6 行,

-- 確認洗掉后的結果
SELECT * FROM Product;

執行結果:

product_id | product_name | product_type | sale_price | purchase_price | regist_date
-----------+--------------+--------------+------------+----------------+-----------
 0001      | T恤衫        | 衣服         |        1000 |             500 | 2009-09-20
 0002      | 打孔器       | 辦公用品     |         500 |             320 | 2009-09-11
 0004      | 菜刀         | 廚房用具     |        3000 |            2800 | 2009-09-20
 0006      | 叉子         | 廚房用具     |         500 |                 | 2009-09-20
 0007      | 擦菜板       | 廚房用具     |         880 |             790 | 2008-04-28
 0008      | 圓珠筆       | 辦公用品     |         100 |                 | 2009-11-11

法則 5

可以通過 WHERE 子句指定物件條件來洗掉部分資料,

SELECT 陳述句不同的是,DELETE 陳述句中不能使用 GROUP BYHAVINGORDER BY 三類子句,而只能使用 WHERE 子句,

原因很簡單,GROUP BYHAVING 是從表中選取資料時用來改變抽取資料形式的,而 ORDER BY 是用來指定取得結果顯示順序的,

因此,在洗掉表中資料時它們都起不到什么作用,

專欄

洗掉和舍棄

標準 SQL 中用來從表中洗掉資料的只有 DELETE 陳述句,但是,很多資料庫產品中還存在另外一種被稱為 TRUNCATE 的陳述句,

這些產品主要包括 Oracle、SQL Server、PostgreSQL、MySQL 和 DB2,

TRUNCATE 是舍棄的意思,具體的使用方法如下所示,

語法 A 只能洗掉表中全部資料的 TRUNCATE 陳述句

TRUNCATE <表名>;

DELETE 不同的是,TRUNCATE 只能洗掉表中的全部資料,而不能通過 WHERE 子句指定條件來洗掉部分資料,

也正是因為它不能具體地控制洗掉物件,所以其處理速度比 DELETE 要快得多,

實際上,DELETE 陳述句在 DML 陳述句中也屬于處理時間比較長的,因此需要洗掉全部資料行時,使用 TRUNCATE 可以縮短執行時間,

但是,產品不同需要注意的地方也不盡相同,

例如在 Oracle 中,把 TRUNCATE 定義為 DDL,而不是 DML(因此,Oracle 中的 TRUNCATE 不能使用 ROLLBACK,執行 TRUNCATE 的同時會默認執行 COMMIT 操作,),

使用 TRUNCATE 時,請大家仔細閱讀使用手冊,多加注意,便利的工具往往還是會存在一些不足之處的,

三、資料的更新(UPDATE 陳述句的使用方法)

本節重點

  • 使用 UPDATE 陳述句可以更改(更新)表中的資料,

  • 更新部分資料行時可以使用 WHERE 來指定更新物件的條件,通過 WHERE 子句指定更新物件的 UPDATE 陳述句稱為搜索型 UPDATE 陳述句,

  • UPDATE 陳述句可以將列的值更新為 NULL

  • 同時更新多列時,可以在 UPDATE 陳述句的 SET 子句中,使用逗號分隔更新物件的多個列,

3.1 UPDATE 陳述句的基本語法

使用 INSERT 陳述句向表中插入資料之后,有時卻想要再更改資料,例如“將商品銷售單價登記錯了”等的時候,

這時并不需要把資料洗掉之后再重新插入,使用 UPDATE 陳述句就可以改變表中的資料了,

INSERT 陳述句、DELETE 陳述句一樣,UPDATE 陳述句也屬于 DML 陳述句,通過執行該陳述句,可以改變表中的資料,其基本語法如下所示,

語法 4 改變表中資料的 UPDATE 陳述句

UPDATE <表名>
   SET <列名> = <運算式>;

將更新物件的列和更新后的值都記述在 SET 子句中,

我們還是以 Product(商品)表為例,由于之前我們洗掉了“銷售單價大于等于 4000 元”的 2 行資料,現在該表中只剩下了 6 行資料了(表 2),

表 2 Product 表

product_id(商品編號) product_name(商品名稱) product_type(商品種類) sale_price(銷售單價) purchase_price(進貨單價) regist_date(登記日期)
0001 T 恤衫 衣服 1000 500 2009-09-20
0002 打孔器 辦公用品 500 320 2009-09-11
0004 菜刀 廚房用具 3000 2800 2009-09-20
0006 叉子 廚房用具 500 2009-09-20
0007 擦菜板 廚房用具 880 790 2008-04-28
0008 圓珠筆 辦公用品 100 2009-11-11

接下來,讓我們嘗試把 regist_date 列(登記日期)的所有資料統一更新為“2009-10-10”,具體的 SQL 陳述句請參見代碼清單 15,

代碼清單 15 將登記日期全部更新為“2009-10-10”

UPDATE Product
   SET regist_date = '2009-10-10';

表中的資料有何變化呢?我們通過 SELECT 陳述句來確認一下吧,

-- 確認更新內容
SELECT * FROM Product ORDER BY product_id;

執行結果:

執行結果

此時,連登記日期原本為 NULL 的資料行(運動 T 恤)的值也更新為 2009-10-10 了,

執行結果

3.2 指定條件的 UPDATE 陳述句(搜索型 UPDATE)

接下來,讓我們看一看指定更新物件的情況,

更新資料時也可以像 DELETE 陳述句那樣使用 WHERE 子句,這種指定更新物件的 UPDATE 陳述句稱為搜索型 UPDATE 陳述句

該陳述句的語法如下所示(與 DELETE 陳述句十分相似),

語法 5 更新部分資料行的搜索型 UPDATE

UPDATE <表名>
   SET <列名> = <運算式>
 WHERE <條件>;

例如,將商品種類(product_type)為廚房用具的記錄的銷售單價(sale_price)更新為原來的 10 倍,請參見代碼清單 16,

代碼清單 16 將商品種類為廚房用具的記錄的銷售單價更新為原來的 10 倍

UPDATE Product
   SET sale_price = sale_price * 10
 WHERE product_type = '廚房用具';

我們可以使用如下 SELECT 陳述句來確認更新后的內容,

-- 確認更新內容
SELECT * FROM Product ORDER BY product_id;

執行結果:

執行結果

該陳述句通過 WHERE 子句中的“product_type = '廚房用具'”條件,將更新物件限定為 3 行,

然后通過 SET 子句中的運算式 sale_price * 10,將原來的單價擴大了 10 倍,

SET 子句中賦值運算式的右邊不僅可以是單純的值,還可以是包含列的運算式,

3.3 使用 NULL 進行更新

使用 UPDATE 也可以將列更新為 NULL(該更新俗稱為 NULL 清空),

此時只需要將賦值運算式右邊的值直接寫為 NULL 即可,

例如,我們可以將商品編號(product_id)為 0008 的資料(圓珠筆)的登記日期(regist_date)更新為 NULL(代碼清單 17),

代碼清單 17 將商品編號為 0008 的資料(圓珠筆)的登記日期更新為 NULL

UPDATE Product
   SET regist_date = NULL
 WHERE product_id = '0008';
-- 確認更新內容
SELECT * FROM Product ORDER BY product_id;

執行結果:

執行結果

INSERT 陳述句一樣,UPDATE 陳述句也可以將 NULL 作為一個值來使用,

但是,只有未設定 NOT NULL 約束和主鍵約束的列才可以清空為 NULL

如果將設定了上述約束的列更新為 NULL,就會出錯,這點與 INSERT 陳述句相同,

法則 6

使用 UPDATE 陳述句可以將值清空為 NULL(但只限于未設定 NOT NULL 約束的列),

3.4 多列更新

UPDATE 陳述句的 SET 子句支持同時將多個列作為更新物件,

例如我們剛剛將銷售單價(sale_price)更新為原來的 10 倍,如果想同時將進貨單價(purchase_price)更新為原來的一半,該怎么做呢?

最容易想到的解決辦法可能就是像代碼清單 18 那樣,執行兩條 UPDATE 陳述句,

代碼清單 18 能夠正確執行的繁瑣的 UPDATE 陳述句

-- 一條UPDATE陳述句只更新一列
UPDATE Product
   SET sale_price = sale_price * 10
 WHERE product_type = '廚房用具';

UPDATE Product
   SET purchase_price = purchase_price / 2
 WHERE product_type = '廚房用具';

雖然這樣也能夠正確地更新資料,但執行兩次 UPDATE 陳述句不但有些浪費,而且增加了 SQL 陳述句的書寫量,

其實,我們可以將其合并為一條 UPDATE 陳述句來處理,合并的方法有兩種,請參見代碼清單 19 和代碼清單 20,

方法 ①:代碼清單 19 將代碼清單 18 的處理合并為一條 UPDATE 陳述句

-- 使用逗號對列進行分隔排列
UPDATE Product
   SET sale_price = sale_price * 10,
       purchase_price = purchase_price / 2
 WHERE product_type = '廚房用具';

方法 ②:代碼清單 20 將代碼清單 18 的處理合并為一條 UPDATE 陳述句

-- 將列用()括起來的清單形式
UPDATE Product
   SET (sale_price, purchase_price) = (sale_price * 10, purchase_price / 2)
 WHERE product_type = '廚房用具';

執行上述兩種 UPDATE 陳述句,都可以得到相同的結果:只有廚房用具的銷售單價(sale_price)和進貨單價(purchase_price)被更新了,

-- 確認更新內容
SELECT * FROM Product ORDER BY product_id;

執行結果:

執行結果

當然,SET 子句中的列不僅可以是兩列,還可以是三列或者更多,

需要注意的是第一種方法——使用逗號將列進行分隔排列(代碼清單 19),這一方法在所有的 DBMS 中都可以使用,

但是第二種方法——將列清單化(代碼清單 20),這一方法在某些 DBMS 中是無法使用的 [8],因此,實際應用中通常都會使用第一種方法,

原文鏈接:https://www.developerastrid.com/sql/sql-insert-delete-update/

(完)


  1. 有關日期型的介紹,請參考 SQL 如何對表進行創建、更新和洗掉操作, ??

  2. 但是使用默認值時列數無需完全一致,相關內容將會在隨后的“插入默認值”中進行介紹, ??

  3. 插入多行的情況,請參考專欄“多行 INSERT”, ??

  4. 不僅是 INSERTDELETEUPDATE 等更新陳述句也一樣,SQL 陳述句執行失敗時都不會對表中資料造成影響, ??

  5. 但即使指定了 ORDER BY 子句也沒有任何意義,因為無法保證表內部記錄的排列順序, ??

  6. INSERT 陳述句相同,資料的更新也是以記錄為基本單位進行的,下一節將要學習的 UPDATE 陳述句也是如此, ??

  7. 雖然“搜索型 DELETE”是正式用語,但實際上這種說法并不常用,而是簡單地稱為 DELETE 陳述句, ??

  8. 可以在 PostgreSQL 和 DB2 中使用, ??

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/499167.html

標籤:SQL Server

上一篇:SQL 如何對表進行聚合和分組查詢并對查詢結果進行排序

下一篇:什么是 SQL 事務,如何創建 SQL 事務

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more