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='員工表'

插入幾條數據:

要求:

新增一個員工時,如果該員工已存在(以員工號f_emp_code作為判斷依據),則更新,否則插入。而且工資f_salary,更新時,不得低於原工資(即:工資只能漲,不能降)。

 

方法一:傳統方法

插入

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'
);

 

更新: 

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條語句,分別處理插入和更新的場景。

 

方法二: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變了,其它子表沒做好同步,會死得很難看。-- 不建議使用該方法!

 

方法三: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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM