SQL 如何插入、刪除和更新數據

来源:https://www.cnblogs.com/vin-c/archive/2022/06/09/16358278.html
-Advertisement-
Play Games

本文將會給大家介紹 DBMS 中用來更新表中數據的方法。SQL 數據的更新處理大體可以分為插入(INSERT)、刪除(DELETE)和更新(UPDATE)三類。本文將會對這三類更新方法進行詳細介紹。 一、數據的插入(INSERT 語句的使用方法) 本節重點 使用 INSERT 語句可以向表中插入數據 ...


目錄

本文將會給大家介紹 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 中使用。 ↩︎


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 英文原文: https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpuacct.html CPU Accounting Controller CPU統計控制器(CPU Accounting Controller)用來分組使用cgr ...
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡巴巴開源鏡像站 前言 最近,學習了胡老師的《ROS入門21講》,在Ubuntu18.04上安裝ROS過程中遇到了一些問題,解決這些問題耗費了大半天,故通過本文進行詳細安裝介紹,以便其他學者在安裝這塊少花時間,把更多的精力放在研究上。 一、環境配置 我的環境:虛 ...
  • 作用:命令行多視窗顯示;命令行程式與本機脫離 1 安裝tmux (1)redhat、centos系統 yum install tmux (2)ubuntu系統 apt-get install tmux 2 使用tmux (1)啟動 首先,我們使用遠程登錄工具,登錄到遠程伺服器上,然後執行下麵的命令: ...
  • 虛擬機關鍵配置名詞解釋 虛擬⽹絡編輯器 橋接模式 可以訪問互聯⽹,配置的地址信息和物理主機⽹段地址信息相同,容易造成地址衝突 NAT模式 可以訪問互聯⽹,配置的地址信息和物理主機⽹段地址信息不同,造成不了地址衝突 僅主機模式 不可以訪問互聯⽹,獲取地址主要⽤於虛擬主機之間溝通,但不能訪問外部⽹絡 網 ...
  • 亂序問題 在業務編寫 FlinkSQL 時, 非常常見的就是亂序相關問題, 在出現問題時,非常難以排查,且無法穩定復現,這樣無論是業務方,還是平臺方,都處於一種非常尷尬的地步。 亂序問題 在業務編寫 FlinkSQL 時, 非常常見的就是亂序相關問題, 在出現問題時,非常難以排查,且無法穩定復現,這 ...
  • 本文給大家介紹資料庫中用來管理數據更新的重要概念——SQL 事務。簡單來講,事務就是需要在同一個處理單元中執行的一系列更新處理的集合。 本文重點 事務是需要在同一個處理單元中執行的一系列更新處理的集合。通過使用事務,可以對資料庫中的數據更新處理的提交和取消進行管理。 事務處理的終止指令包括 COMM ...
  • 在MySQL 5.7版本,官方稱為enhanced multi-threaded slave(簡稱MTS),複製延遲問題已經得到了極大的改進,可以說在MySQL 5.7版本後,複製延遲問題永不存在。 5.7的MTS本身就是:master基於組提交(group commit)來實現的併發事務分組,再由 ...
  • 導讀: 驗證碼作為網路安全的第一道屏障,其重要程度不言而喻。當前,捲積神經網路的高速發展使得許多驗證碼的安全性大大降低,一些新型驗證碼甚至選擇犧牲可用性從而保證安全性。針對對抗樣本技術的研究,給驗證碼領域帶來了新的契機,並已應用於驗證碼反識別當中,為這場曠日持久攻防對抗註入了新的活力。 分享內容包括 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...