天天看點

SQL插入、替換、更新總結

1.插入或替換

如果我們想插入一條新記錄(INSERT),但如果記錄已經存在,就先删除原記錄,再插入新記錄。

情景示例:這張表存的每個客戶最近一次交易訂單資訊,要求保證單個使用者資料不重複錄入,且執行效率最高,與資料庫互動最少,支撐資料庫的高可用。

此時,可以使用"REPLACE INTO"語句,這樣就不必先查詢,再決定是否先删除再插入。

"REPLACE INTO"語句是基于唯一索引或主鍵來判斷唯一(是否存在)的!

注意事項:如下SQL所示,需要在username字段上建立唯一索引(Unique),transId設定自增即可。

-- 20點充值
REPLACE INTO last_transaction (transId,username,amount,trans_time,remark) 
   VALUES (null, 'chenhaha', 30, '2020-06-11 20:00:20', '會員充值');
 
-- 21點買皮膚
REPLACE INTO last_transaction (transId,username,amount,trans_time,remark) 
   VALUES (null, 'chenhaha', 100, '2020-06-11 21:00:00', '購買盲僧至高之拳皮膚');
           

若username='chenhaha’的記錄不存在,REPLACE語句将插入新記錄(首次充值),否則,目前username='chenhaha’的記錄将被删除,然後再插入新記錄。

id不要給具體值,不然會影響SQL執行,業務有特殊需求除外。

2.插入或更新

如果我們希望插入一條新記錄(INSERT),但如果記錄已經存在,就更新該記錄,此時,可以使用"INSERT INTO … ON DUPLICATE KEY UPDATE …"語句:

情景示例:這張表存了使用者曆史充值金額,如果第一次充值就新增一條資料,如果該使用者充值過就累加曆史充值金額,需要保證單個使用者資料不重複錄入。

這時可以使用"INSERT INTO … ON DUPLICATE KEY UPDATE …"語句。

注意事項:同上,"INSERT INTO … ON DUPLICATE KEY UPDATE …"語句是基于唯一索引或主鍵來判斷唯一(是否存在)的。如下SQL所示,需要在username字段上建立唯一索引(Unique),transId設定自增即可。
-- 使用者陳哈哈充值了30元買會員
INSERT INTO total_transaction (t_transId,username,total_amount,last_transTime,last_remark) 
   VALUES (null, 'chenhaha', 30, '2020-06-11 20:00:20', '充會員') 
   ON DUPLICATE KEY UPDATE  total_amount=total_amount + 30, last_transTime='2020-06-11 20:00:20', last_remark ='充會員';
 
-- 使用者陳哈哈充值了100元買瞎子至高之拳皮膚
INSERT INTO total_transaction (t_transId,username,total_amount,last_transTime,last_remark) 
   VALUES (null, 'chenhaha', 100, '2020-06-11 20:00:20', '購買盲僧至高之拳皮膚') 
   ON DUPLICATE KEY UPDATE total_amount=total_amount + 100, last_transTime='2020-06-11 21:00:00', last_remark ='購買盲僧至高之拳皮膚';
           

若username='chenhaha’的記錄不存在,INSERT語句将插入新記錄,否則,目前username='chenhaha’的記錄将被更新,更新的字段由UPDATE指定。

3.插入或忽略

如果我們希望插入一條新記錄(INSERT),但如果記錄已經存在,就啥事也不幹直接忽略,此時,可以使用INSERT IGNORE INTO …語句:情景很多,不再舉例贅述。

注意事項:同上,"INSERT IGNORE INTO

…"語句是基于唯一索引或主鍵來判斷唯一(是否存在)的,需要在username字段上建立唯一索引(Unique),transId設定自增即可。

-- 使用者首次添加
INSERT IGNORE INTO users_info (id, username, sex, age ,balance, create_time) 
   VALUES (null, 'chenhaha', '男', 12, 0, '2020-06-11 20:00:20');
 
-- 二次添加,直接忽略
INSERT IGNORE INTO users_info (id, username, sex, age ,balance, create_time) 
   VALUES (null, 'chenhaha', '男', 12, 0, '2020-06-11 21:00:20');
           

若username='chenhaha’的記錄不存在,INSERT語句将插入新記錄,否則,不執行任何操作。

4.SQL中的if-else判斷語句

衆所周知,if-else判斷在任何地方都很有用,在SQL語句中,"CASE WHEN … THEN … ELSE … END"語句可以用在增删改查各類語句中。

給個情景:婦女節大回饋,2020年注冊的新使用者,所有成年女性賬号送10元紅包,其他使用者送5元紅包,自動充值。 示例語句如下:
-- 送紅包語句
UPDATE users_info u 
    SET u.balance = CASE WHEN u.sex ='女' and u.age > 18 THEN u.balance + 10 
                         ELSE u.balance + 5 end 
                         WHERE u.create_time >= '2020-01-01'
           

情景2:有個學生聯考分數表,需要将等級列出來,650分以上是重點大學,600-650是一本,500-600分是二本,400-500是三本,400以下大專;

原測試資料如下:

SQL插入、替換、更新總結

查詢語句:

SELECT *,case when total_score >= 650  THEN '重點大學' 
              when total_score >= 600 and total_score <650 THEN '一本'
              when total_score >= 500 and total_score <600 THEN '二本'
              when total_score >= 400 and total_score <500 THEN '三本'        
              else '大專' end as status_student 
              from student_score;
           

查詢結果:

SQL插入、替換、更新總結

5.指定資料快照或備份

如果想要對一個表進行快照,即複制一份目前表的資料到一個新表,可以結合CREATE TABLE和SELECT:
-- 對class_id=1(一班)的記錄進行快照,并存儲為新表students_of_class1:
CREATE TABLE students_of_class1 SELECT * FROM student WHERE class_id=1;
新建立的表結構和SELECT使用的表結構完全一緻。
           

6.強制使用指定索引

在查詢的時候,資料庫系統會自動分析查詢語句,并選擇一個最合适的索引。但是很多時候,資料庫系統的查詢優化器并不一定總是能使用最優索引。如果我們知道如何選擇索引,可以使用FORCE INDEX強制查詢使用指定的索引。例如:

注意:指定索引的前提是索引idx_class_id必須存在。

7.本文考題:

查詢24h内每隔10分鐘為一時間段的網站通路量

注:表名為data_timing,時間字段為createTime

每小時的通路量:

SELECT DATE_FORMAT(p.createTime, '%H') as date_str,count(*) as count 
    from data_timing p
	where DATE_FORMAT(p.createTime, '%Y-%m-%d %H:%i:%S') >= DATE_FORMAT('2020-01-14 00:00:00', '%Y-%m-%d %H:%i:%S')
	    AND DATE_FORMAT(p.createTime, '%Y-%m-%d %H:%i:%S') < DATE_FORMAT('2020-01-15 00:00:00', '%Y-%m-%d %H:%i:%S')
		GROUP BY HOUR(p.createTime)
           

最終上sql—每10分鐘的通路量:

SELECT concat( date_format( p.createTime, '%Y-%m-%d %H:' ) , floor( date_format( p.createTime, '%i' ) /10 )*10 ) as date_str
, count(*) as count from data_timing p
    where DATE_FORMAT(p.createTime, '%Y-%m-%d %H:%i:%S') < DATE_FORMAT('2020-01-15 00:00:00', '%Y-%m-%d %H:%i:%S')
        AND DATE_FORMAT(p.createTime, '%Y-%m-%d %H:%i:%S') >= DATE_FORMAT('2020-01-14 00:00:00', '%Y-%m-%d %H:%i:%S')
        GROUP BY  concat( date_format( p.createTime, '%Y-%m-%d %H:' ) , floor( date_format( p.createTime, '%i' ) /10 ))
           

表查詢結果如下:

SQL插入、替換、更新總結

總結

好的sql語句不僅可以提高代碼執行效率,還可以為自己節省更多的工作成本,何樂而不為呢!分享知識,努力進步,關注我,每天給大家帶來新的知識!