先建一個表,便於後面討論:mysql
CREATE TABLE `t_emp` ( `f_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵id', `f_emp_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '員工號', `f_emp_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '員工姓名', `f_city` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '所屬城市', `f_salary` int(11) DEFAULT '1200' COMMENT '工資', `f_last_update_time` datetime(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '最後修改時間', PRIMARY KEY (`f_id`), UNIQUE KEY `idx_emp_code` (`f_emp_code`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='員工表'
插入幾條數據:
sql
要求:spa
新增一個員工時,若是該員工已存在(以員工號f_emp_code做爲判斷依據),則更新,不然插入。並且工資f_salary,更新時,不得低於原工資(即:工資只能漲,不能降)。.net
方法一:傳統方法code
插入blog
INSERT INTO t_emp( f_emp_code , f_emp_name , f_city , f_salary ) SELECT '10007' , '新人' , '西安' , 1000 FROM DUAL WHERE NOT EXISTS( SELECT * FROM t_emp WHERE f_emp_code = '10007' );
更新: ci
UPDATE t_emp SET f_emp_name = '新人2' , f_city = '西安' , f_salary = IF(1000 > f_salary , 1000 , f_salary) WHERE f_emp_code = '10007'
缺點就是得寫2條語句,分別處理插入和更新的場景。get
方法二:replace into同步
REPLACE INTO t_emp( f_emp_code , f_emp_name , f_city , f_salary ) VALUES( '10007' , '新人' , '西安' , IF(1000 > f_salary , 1000 , f_salary));
replace into至關於,先檢測該記錄是否存在(根據表上的惟一鍵),若是存在,先delete,而後再insert。 這個方法有一個很大的問題,若是記錄存在,每次執行完,主鍵自增id就變了(至關於從新insert了一條),對於有複雜關聯的業務場景,若是主表的id變了,其它子表沒作好同步,會死得很難看。-- 不建議使用該方法!it
方法三:on duplicate key
INSERT INTO t_emp( f_emp_code , f_emp_name , f_city , f_salary) VALUES( '10007' , '新人' , '西安' , 1000) ON DUPLICATE KEY UPDATE f_emp_code = values(f_emp_code) , f_emp_name = values(f_emp_name), f_city = values(f_city), f_salary = if(values(f_salary)>f_salary,values(f_salary),f_salary);
注意上面的on duplicate key,遇到重複鍵(即:違反了惟一約束),這時會作update,不然作insert。該方法,沒有replace into的反作用,不會致使已存在記錄的自增id變化。可是有另一個問題,若是這個表上有不止一個惟一約束,在特定版本的mysql中容易產生dead lock(死鎖),見網友文章https://blog.csdn.net/pml18710973036/article/details/78452688