1. 程式人生 > >mysql筆記之插入&鍵值重複解決

mysql筆記之插入&鍵值重複解決

建立表並插入資料

create table t select_info;

 MariaDB [test]> create table t2 select user,host password from mysql.user where user='root';
 MariaDB [test]> select * from t2;
 +------+-------------+
 | user | password    |
 +------+-------------+
 | root | 127.0.0.1   |
 | root | ::1         |
 | root | localhost   |
 | root | zabbix\_ser |
 +------+-------------+
 4 rows in set (0.00 sec)

create table t as select_info

 MariaDB [test]> create table t3(user char(20),host char(20),password char(50)) as select user,host,password from mysql.user where user='root'; 
 Query OK, 4 rows affected (0.01 sec)
 Records: 4  Duplicates: 0  Warnings: 0
 
 MariaDB [test]> select * from t3;
 +------+-------------+-------------------------------------------+
 | user | host        | password                                  |
 +------+-------------+-------------------------------------------+
 | root | localhost   | *23AE809DDACAF96AF0FD78ED04B6A265E05AA257 |
 | root | zabbix\_ser |                                           |
 | root | 127.0.0.1   |                                           |
 | root | ::1         |                                           |
 +------+-------------+-------------------------------------------+
 4 rows in set (0.00 sec)
這些語句檢索資料,並按照檢索目標欄位新建一張表,表必須不能已經存在,除非使用or replace或者if not exists子句

只建立表結構,不插入資料:

 create table t1 like t2      --建立完全相同的表結構
 create table tbl_name1 select v1,v2,v3 from t2 where 1=0;  # where false。--可以篩選部分欄位作為新表的結構

鍵值重複

 使用ignore關鍵字忽略所有錯誤行,使insert操作繼續插入後面的資料。
 使用insert ... on duplicate key update,將有重複值的行update為新的值。
 使用replace into語句替代insert into語句,將有重複值的行替換為新行

ignore

準備測試環境

 MariaDB [test]> insert into t4 values
     -> (1,'man','zs'),
     -> (2,'man','ls'),
     -> (3,'man','ww'),
     -> (4,'women','xh'),
     -> (5,'women','xl'),
     -> (6,'women','xb'),
     -> (7,'man','ld'),
     -> (8,'women','hj'),
     -> (9,'men','lk');
 Query OK, 9 rows affected (0.00 sec)
 Records: 9  Duplicates: 0  Warnings: 0
 
 MariaDB [test]> select * from t4;
 +----+-------+------+
 | id | sex   | name |
 +----+-------+------+
 |  1 | man   | zs   |
 |  2 | man   | ls   |
 |  3 | man   | ww   |
 |  4 | women | xh   |
 |  5 | women | xl   |
 |  6 | women | xb   |
 |  7 | man   | ld   |
 |  8 | women | hj   |
 |  9 | men   | lk   |
 +----+-------+------+
 9 rows in set (0.00 sec)
插入資料
 MariaDB [test]> insert into t4 values(5,'women','lw'),(10,'man','sg');
 ERROR 1062 (23000): Duplicate entry '5' for key 'PRIMARY'
 
 MariaDB [test]> select * from t4 where id=5 or id=10;
 +----+-------+------+
 | id | sex   | name |
 +----+-------+------+
 |  5 | women | xl   |
 +----+-------+------+
 1 row in set (0.00 sec)
使用ignore關鍵字
 MariaDB [test]> insert ignore into t4 values(5,'yao','lll'),(10,'ttt','666');
 Query OK, 1 row affected, 1 warning (0.00 sec)
 Records: 2  Duplicates: 1  Warnings: 1
 
 MariaDB [test]> select * from t4 where id=5 or id=10;
 +----+-------+------+
 | id | sex   | name |
 +----+-------+------+
 |  5 | women | xl   |
 | 10 | ttt   | 666  |
 +----+-------+------+
 2 rows in set (0.00 sec)

使用 on duplicate key update子句修改重複值記錄

兩種情況:
1.插入的記錄沒有鍵值衝突
 帶不帶都無所謂了
2.插入的記錄有鍵值重複衝突
 帶有 on duplicate key update 子句會更新表中原有的記錄
測試

MariaDB [test]> select * from t5; ±—±-----±-----+ | id | sex | name | ±—±-----±-----+ | 1 | xx | qq | | 2 | xx | ww | | 3 | yy | ee | ±—±-----±-----+ 3 rows in set (0.00 sec)

插入的記錄沒有鍵值衝突
 MariaDB [test]> insert into t5 values(4,'xx','rr'),(5,'yy','tt');
 Query OK, 2 rows affected (0.00 sec)
 Records: 2  Duplicates: 0  Warnings: 0
插入的記錄有鍵值重複衝突
 MariaDB [test]> insert into t5 values(4,'xx','rrrr'),(6,'yy','yy') on duplicate key update name='rrrr';
 Query OK, 3 rows affected (0.00 sec)
 Records: 2  Duplicates: 1  Warnings: 0
 
 MariaDB [test]> select * from t5;
 +----+------+------+
 | id | sex  | name |
 +----+------+------+
 |  1 | xx   | qq   |
 |  2 | xx   | ww   |
 |  3 | yy   | ee   |
 |  4 | xx   | rrrr |
 |  5 | yy   | tt   |
 |  6 | yy   | yy   |
 +----+------+------+
 6 rows in set (0.00 sec)
還可以在update子句中利用函式 VALUES(col_name)引用insert 部分列值
 MariaDB [test]> insert into t5 values(4,'xx','rrrr') on duplicate key update name=concat('yy',values(id));
 Query OK, 2 rows affected (0.08 sec)
 
 MariaDB [test]> select * from t5;
 +----+------+------+
 | id | sex  | name |
 +----+------+------+
 |  1 | xx   | qq   |
 |  2 | xx   | ww   |
 |  3 | yy   | ee   |
 |  4 | xx   | yy4  |
 |  5 | yy   | tt   |
 |  6 | yy   | yy   |
 +----+------+------+
 6 rows in set (0.00 sec)

PS:VALUES函式只在insert … on duplicate key update 語句中有意義,其他則返回NULL。

insert — on duplicate key update 執行原理

 插入新行,判斷是否和已有記錄存在鍵值衝突,若有,則更新舊行為新行(先觸發before update 觸發器,更新後觸發after update)

replace into 語句,

 在沒有鍵值衝突時,完全等價與insert into ,有鍵值衝突時,會將新行替換舊行
測試
 MariaDB [test]> select * from t5;
 +----+------+------+
 | id | sex  | name |
 +----+------+------+
 |  1 | xx   | qq   |
 |  2 | xx   | ww   |
 |  3 | yy   | ee   |
 |  4 | xx   | yy4  |
 |  5 | yy   | tt   |
 |  6 | yy   | yy   |
 +----+------+------+
 6 rows in set (0.00 sec)
 
 MariaDB [test]> replace into t5 values(4,'yy','xx');
 Query OK, 2 rows affected (0.00 sec)
 
 MariaDB [test]> select * from t5;
 +----+------+------+
 | id | sex  | name |
 +----+------+------+
 |  1 | xx   | qq   |
 |  2 | xx   | ww   |
 |  3 | yy   | ee   |
 |  4 | yy   | xx   |
 |  5 | yy   | tt   |
 |  6 | yy   | yy   |
 +----+------+------+
 6 rows in set (0.00 sec)
replace into 執行原理
 插入新行,判斷是否衝突(觸發before insert觸發器),若有,則刪除舊行,並插入新行(before delete —> after delete -> after insert)