insert 語句有三種語法:
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[(col_name [, col_name] ...)]
{ {VALUES | VALUE} (value_list) [, (value_list)] ...
|
VALUES row_constructor_list
}
[AS row_alias[(col_alias [, col_alias] ...)]]
[ON DUPLICATE KEY UPDATE assignment_list]
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[AS row_alias[(col_alias [, col_alias] ...)]]
SET assignment_list
[ON DUPLICATE KEY UPDATE assignment_list]
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[(col_name [, col_name] ...)]
[AS row_alias[(col_alias [, col_alias] ...)]]
{SELECT ... | TABLE table_name}
[ON DUPLICATE KEY UPDATE assignment_list]
value:
{expr | DEFAULT}
value_list:
value [, value] ...
row_constructor_list:
ROW(value_list)[, ROW(value_list)][, ...]
assignment:
col_name = [row_alias.]value
assignment_list:
assignment [, assignment] ...
- 1、INSERT 語句向已存在的表插入新行, INSERT ... VALUES, INSERT ... VALUES ROW(), 和 INSERT ... SET 這三種形式需要明確指定列的值,而 INSERT ... SELECT 形式是插入從其他一個或多個表查詢的結果。
- 2、ON DUPLICATE KEY UPDATE 從句可以在 插入包含UNIQUE 索引 或 PRIMARY KEY 的列,且遇到該列的值已存在的情況時,選擇更新其他列,而不至於報錯。
- 3、MySQL 8.0.19 及以后的版本中: 1) 可以使用 INSERT ... TABLE 來插入單表;2) 可以將插入行起個別名,用到 ON DUPLICATE KEY UPDATE 從句中,簡化書寫。
- 4、完整的 INSERT 語句需要: 插入權限,更新權限,查詢權限。
- 5、插入有分區的表時,需要使用 PARTITION 從句,后接分區名。如果插入行沒有匹配到分區,則失敗
- 6、插入語句:1)如果指定了列名(可以部分列名),值可以通過 VALUES , VALUES ROW() , or SELECT 語句給出,值的順序和列名的順序要一致。2)如果沒有指定列名,則需要給出全部列的值,其順序與表結構中列的順序一致。
- 7、在非 SQL 嚴格模式下,沒有指定的列則會用默認值(或隱式默認值)插入。而在嚴格模式下,如果某個列沒有指定默認值,且插入時沒有給該列指定一個值,則會報錯。建議 使用 DEFAULT 明確地設置列的默認值。
- 8、如果列名和列值都為空,則插入一個所有列都是默認值的行
INSERT INTO tbl_name () VALUES();
- 9、給會自動生成值的列指定值,只能指定 DEFAULT。自動生成值的列,指的是其值是通過其他列計算得到的,在創建表時指定了表達式。
- 10、使用表達式時,可使用 DEFAULT(col_name) 給該列指定默認值
- 11、在表達式中,可能會出現類型轉換。比如字符串 '1999.0e-2' 在插入 INT, FLOAT, DECIMAL(10,6), YEAR 類型的列時,會分別轉換為 1999, 19.9921, 19.992100, 1999
- 12、使用表達式時,可以使用值列表中之前已經設置過的列。如果參考使用的是 AUTO_INCREMENT 的列(自增列沒有指定值),則自增列返回的值是0,因為 AUTO_INCREMENT 列是在其他列都賦值之后才生成的。
# 在設置 col2 的值時,使用了col1
INSERT INTO tbl_name (col1,col2) VALUES(15, col1*2);
# id 列自增,結果 col2 的值是 0
INSERT INTO tbl_name (col1,col2) VALUES(15, id*2);
# id 列自增,結果 col2 的值是 200
INSERT INTO tbl_name (id,col1,col2) VALUES(100,15, id*2);
# id 列自增,結果 col2 的值是 0
INSERT INTO tbl_name (id,col1,col2) VALUES(default, 15, id*2);
- 13、多行插入
# 使用 values 形式
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3), (4,5,6), (7,8,9);
# 使用 values row 形式
INSERT INTO tbl_name (a,b,c) VALUES ROW(1,2,3), ROW(4,5,6), ROW(7,8,9);
-
14、使用 LOW_PRIORITY 修飾符,會延遲插入,等到沒有其他客戶端讀取這個表時,才執行插入語句,即插入優先級低於讀取優先級。 使用HIGH_PRIORITY 修飾符 提高 插入優先級,會覆蓋 --low-priority-updates 選項的作用。
LOW_PRIORITY 和 HIGH_PRIORITY都只會影響使用表級鎖的引擎(如 MyISAM, MEMORY, and MERGE),也都會造成不能並發插入數據。 -
15、使用 IGNORE 修飾符,會在執行插入語句時忽略一些可忽略的錯誤(並不是全部錯誤),而繼續完成數據的插入。比如 UNIQUE 索引 or PRIMARY KEY 的列 重復數據插入 的錯誤,就會忽略,但數據不會新增。
-
16、
- 1) INSERT ... SELECT 語句,可以通過查詢語句(SELECT)實現快速插入
- 2)從 MySQL 8.0.19 版本開始,可以使用TABLE 代替 SELECT,用來將源表中的所有列插入到目標表中。 TABLE tb 等價於 SELECT * FROM tb。
- 3)INSERT語句的目標表可能出現在查詢的SELECT部分的FROM子句中,或者作為TABLE 命名的表。但是,不能在子查詢中插入表同一表中的數據。
能通過INSERT... SELECT 語句插入同一個表的數據,是因為MySQL會創建一個內部臨時表來保存SELECT中的行,然后將這些行插入到目標表中。另外該表本身不能是臨時表。 - 4) INSERT ... SELECT 不允許並發插入
- 5) INSERT ... SELECT 允許在 SELECT部分使用 別名,但 TABLE 語句不支持別名
TABLE table_name [ORDER BY column_name] [LIMIT number [OFFSET number]]
INSERT INTO tbl_temp2 (fld_id)
SELECT tbl_temp1.fld_order_id
FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
# 從 MySQL 8.0.19 版本開始,可以使用TABLE 代替 SELECT
INSERT INTO ta TABLE tb;
# 插入本表中的數據
INSERT INTO computer_room (room_name, room_address, room_maintainer, creator_id)
SELECT room_name, room_address, room_maintainer, creator_id FROM computer_room WHERE id=7
- 17、INSERT ... ON DUPLICATE KEY UPDATE, 可以處理 UNIQUE index or PRIMARY KEY 列 重復數據的問題
- 1)ON DUPLICATE KEY UPDATE 從句 盡量避免包含多個唯一鍵的列,因為多個唯一鍵的列可能會匹配到多行,但也只修改一行。
- 2)影響行數:如果插入新行是1;如果是更新行是2;如果新設置的值和原來一樣是0,但當連接到mysqld使用 mysql_real_connect() C API 函數且指定了CLIENT_FOUND_ROWS 標志,結果仍然是1,而不是0。
- 3)無論是新增還是更新, LAST_INSERT_ID() 函數 返回的都是 AUTO_INCREMENT 的值
# a 是 唯一鍵,且已存在 a 為1的 行
# 下面兩個語句,結果類似:數據都會一樣,只是對於 InnoDB 的表 且 a 是自增的列 ,INSERT語句會增加 auto-incremen (自增)的值,UPDATE 語句不會。
INSERT INTO t1 (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE t1 SET c=c+1 WHERE a=1;
# 使用 VALUES(col_name),獲取語句中的相應列的值
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
# 等價於下面兩句
INSERT INTO t1 (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=3;
INSERT INTO t1 (a,b,c) VALUES (4,5,6)
ON DUPLICATE KEY UPDATE c=9;
# MySQL 8.0.19 后, 使用別名 替代 VALUES,獲取語句中的值 ,別名要唯一,能夠區分
# 行別名
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new
ON DUPLICATE KEY UPDATE c = new.a+new.b;
# 列別名,行別名依舊要有
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new(m,n,p)
ON DUPLICATE KEY UPDATE c = m+n;
# set 形式語句
INSERT INTO t1 SET a=1,b=2,c=3 AS new
ON DUPLICATE KEY UPDATE c = new.a+new.b;
INSERT INTO t1 SET a=1,b=2,c=3 AS new(m,n,p)
ON DUPLICATE KEY UPDATE c = m+n;
## 從 MySQL 8.0.20 開始,INSERT ... SELECT ... ON DUPLICATE KEY UPDATE 中的 UPDATE 使用 VALUES(),會拋出warning
INSERT INTO t1
SELECT c, c+d FROM t2
ON DUPLICATE KEY UPDATE b = VALUES(b);
# 使用子查詢替換,就不會有警告
INSERT INTO t1
SELECT * FROM (SELECT c, c+d AS e FROM t2) AS dt
ON DUPLICATE KEY UPDATE b = e;
# 直接使用聯合查詢會報錯
INSERT INTO t1 (a, b)
SELECT c, d FROM t2
UNION
SELECT e, f FROM t3
ON DUPLICATE KEY UPDATE b = b + c;
# 需要 將聯合查詢作為一個整體的導出表
INSERT INTO t1 (a, b)
SELECT * FROM
(SELECT c, d FROM t2
UNION
SELECT e, f FROM t3) AS dt
ON DUPLICATE KEY UPDATE b = b + c;
- 18、DELAYED 修飾符: 在 MySQL 5.6 就過時了,在 MySQL8.0 后 已經不支持了,會忽略這個關鍵詞。其過程是:立即響應發起插入請求的客戶端,但插入語句先排隊,等到該表沒有其他線程使用時執行插入語句。
https://dev.mysql.com/doc/refman/8.0/en/insert.html
https://dev.mysql.com/doc/refman/8.0/en/insert-select.html
https://dev.mysql.com/doc/refman/8.0/en/table.html
https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html