Snowflake 的 Time Travel 功能允許使用者查詢過去一段時間內的資料狀態,這對於資料還原和稽核追蹤至關重要。當誤刪資料時,可以利用 Time Travel 功能輕鬆還原資料。文章首先介紹瞭如何使用 DELETE 陳述式刪除資料,接著說明如何使用 AT 子句配合 OFFSET 引數查詢特定時間點的資料表狀態,並使用 INSERT INTO 陳述式將過去的資料重新插入資料表,實作資料還原。除了資料還原,文章也涵蓋了 UPDATE 陳述式的用法,包含單表更新和多表連線更新,並提醒開發者注意多表連線更新可能產生的非預期結果。最後,文章詳細講解了 MERGE 陳述式,它能夠在單一操作中完成插入、更新和刪除資料,簡化資料合併流程,並提供一個實際案例說明如何使用 MERGE 陳述式合併兩個資料表。
資料刪除與還原:Snowflake 的 Time Travel 功能
在資料函式倉管理中,刪除資料是一項常見的操作。然而,一旦資料被刪除,要還原它們就變得相當困難。幸運的是,Snowflake 提供了一個名為 Time Travel 的功能,讓使用者能夠檢視資料在特定時間點的狀態。
使用 DELETE 陳述式刪除資料
在 Snowflake 中,可以使用 DELETE 陳述式從資料表中刪除特定的資料列。例如,若要從 Person 資料表中刪除與 Employee 資料表中相同名字的資料列,可以使用以下 SQL 陳述式:
DELETE FROM person
USING employee
WHERE employee.emp_name = CONCAT(person.first_name, ' ', person.last_name);
內容解密:
DELETE FROM person指定了要從Person資料表中刪除資料。USING employee表示使用Employee資料表來進行連線操作。WHERE子句中的條件employee.emp_name = CONCAT(person.first_name, ' ', person.last_name)用於匹配兩個資料表中的名字。CONCAT函式用於將Person資料表中的first_name和last_name合併成一個完整的姓名,以便與Employee資料表中的emp_name進行比較。
Time Travel:還原被刪除的資料
如果在刪除資料後發現需要還原它們,Snowflake 的 Time Travel 功能可以幫助實作這一點。透過使用 AT 子句,可以查詢特定時間點的資料狀態。例如,若要查詢 10 分鐘前的 Employee 資料表狀態,可以使用以下 SQL 陳述式:
SELECT * FROM employee AT(OFFSET => -600)
WHERE emp_name = 'Greg Carpenter';
內容解密:
SELECT * FROM employee AT(OFFSET => -600)表示查詢Employee資料表在 600 秒(即 10 分鐘)前的狀態。WHERE emp_name = 'Greg Carpenter'用於篩選出特定的員薪水料。
查詢到需要的資料後,可以使用 INSERT INTO 陳述式將這些資料重新插入到資料表中:
INSERT INTO employee
SELECT * FROM employee AT(OFFSET => -600)
WHERE emp_name = 'Greg Carpenter';
內容解密:
INSERT INTO employee指定了要插入資料的目標資料表。- 子查詢
SELECT * FROM employee AT(OFFSET => -600) WHERE emp_name = 'Greg Carpenter'用於檢索 10 分鐘前被刪除的 Greg Carpenter 的資料。
更新資料:使用 UPDATE 陳述式
除了刪除和還原資料外,更新現有的資料也是常見的操作。可以使用 UPDATE 陳述式來修改特定的資料列。例如,若要更新 Kathy Little 的職業和眼睛顏色,可以使用以下 SQL 陳述式:
UPDATE person
SET occupation = 'musician', eye_color = 'grey'
WHERE first_name = 'Kathy' AND last_name = 'Little';
內容解密:
UPDATE person指定了要更新的資料表。SET occupation = 'musician', eye_color = 'grey'定義了要更新的欄位及其新值。WHERE first_name = 'Kathy' AND last_name = 'Little'用於指定要更新的特定資料列。
結合其他資料表更新資料
Snowflake 也允許在 UPDATE 陳述式中使用 FROM 子句來結合其他資料表進行更新。例如,若要根據 Employee 資料表中的資訊更新 Person 資料表中 Bob Smith 的職業,可以使用以下 SQL 陳述式:
UPDATE person AS p
SET occupation = 'boss'
FROM employee AS e
WHERE e.emp_name = CONCAT(p.first_name, ' ', p.last_name)
AND e.mgr_empid IS NULL;
內容解密:
UPDATE person AS p指定了要更新的資料表及其別名。SET occupation = 'boss'定義了要更新的欄位及其新值。FROM employee AS e表示結合Employee資料表進行更新。WHERE子句中的條件用於匹配兩個資料表中的名字,並進一步篩選出經理員工(即mgr_empid IS NULL)。
資料更新與合併操作詳解
在資料函式倉管理中,更新和合併資料是常見的操作。本文將詳細介紹如何在 Snowflake 中使用 UPDATE 和 MERGE 陳述式來修改資料表中的資料。
使用 UPDATE 陳述式更新資料
UPDATE 陳述式用於修改資料表中的現有資料。以下是一個簡單的例子,展示如何更新 Person 表中的 occupation 欄位:
UPDATE person AS p
SET p.occupation = 'boss'
FROM employee AS e
WHERE e.first_name = p.first_name
AND e.last_name = p.last_name
AND e.mgr_empid IS NULL;
內容解密:
UPDATE person AS p:指定要更新的資料表為person,並給予別名p。SET p.occupation = 'boss':將occupation欄位的值設定為'boss'。FROM employee AS e:指定要連線的資料表為employee,並給予別名e。WHERE e.first_name = p.first_name AND e.last_name = p.last_name AND e.mgr_empid IS NULL;:設定連線條件和篩選條件,只有當employee表中的first_name和last_name與person表相匹配,且mgr_empid為NULL時,才更新對應的occupation欄位。
多表連線更新的注意事項
當使用多表連線進行更新時,需要注意連線的結果是否符合預期。以下是一個可能導致非預期結果的例子:
UPDATE person AS p
SET p.years_of_education = e.empid - 1000
FROM employee AS e
WHERE e.empid < 1003;
內容解密:
- 如果
person表中的某一行與employee表中的多行相匹配,則該行將被多次更新,最終的值取決於最後一次更新的結果。 - 在這個例子中,由於
empid < 1003的條件導致多行匹配,因此所有person表中的行都被更新為相同的值。
使用 MERGE 陳述式合併資料
MERGE 陳述式允許在單一操作中插入、更新或刪除資料。以下是一個例子,展示如何使用 MERGE 陳述式根據 Person_Refresh 表的內容更新 Person 表:
MERGE INTO person AS p
USING person_refresh AS pr
ON p.first_name = pr.fname AND p.last_name = pr.lname
WHEN MATCHED AND pr.remove = 'yes' THEN DELETE
WHEN MATCHED THEN UPDATE SET p.birth_date = pr.dob,
p.eye_color = pr.eyes,
p.occupation = pr.profession
WHEN NOT MATCHED THEN INSERT (p.first_name, p.last_name, p.birth_date, p.eye_color, p.occupation)
VALUES (pr.fname, pr.lname, pr.dob, pr.eyes, pr.profession);
內容解密:
MERGE INTO person AS p USING person_refresh AS pr:指定目標表為person,源表為person_refresh。ON p.first_name = pr.fname AND p.last_name = pr.lname:設定匹配條件。WHEN MATCHED AND pr.remove = 'yes' THEN DELETE:如果匹配且remove欄位為'yes',則刪除該行。WHEN MATCHED THEN UPDATE SET ...:如果匹配,則更新指定的欄位。WHEN NOT MATCHED THEN INSERT ...:如果不匹配,則插入新行。
圖表翻譯:
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Snowflake 資料表操作與 Time Travel 功能
package "資料庫架構" {
package "應用層" {
component [連線池] as pool
component [ORM 框架] as orm
}
package "資料庫引擎" {
component [查詢解析器] as parser
component [優化器] as optimizer
component [執行引擎] as executor
}
package "儲存層" {
database [主資料庫] as master
database [讀取副本] as replica
database [快取層] as cache
}
}
pool --> orm : 管理連線
orm --> parser : SQL 查詢
parser --> optimizer : 解析樹
optimizer --> executor : 執行計畫
executor --> master : 寫入操作
executor --> replica : 讀取操作
cache --> executor : 快取命中
master --> replica : 資料同步
note right of cache
Redis/Memcached
減少資料庫負載
end note
@enduml圖表翻譯: 此圖示展示了 MERGE 陳述式的流程,首先檢查匹配條件,然後根據條件執行刪除、更新或插入操作。
資料生成、轉換與操作
在前一章中,我們探討了Snowflake中可用的不同資料型別,包括數值、時間和字元。本章將深入研究Snowflake內建的函式,用於生成、轉換和操作這些資料型別的值。
操作字元資料
Snowflake提供了豐富的函式來處理字元資料,無論是連線字串、搜尋子字串、轉換大小寫還是其他操作。
字串生成與操作
建立字串的方法很簡單,只需將字串內容用單引號括起來即可:
PUBLIC>select '這是我的字串';
+
---
-
---
-
---
-
---
-
---
--+
| '這是我的字串' |
|
---
-
---
-
---
-
---
-
---
--|
| 這是我的字串 |
+
---
-
---
-
---
-
---
-
---
--+
如果需要連線兩個或多個字串,可以使用 || 運算子或內建的 concat() 函式:
PUBLIC>select '字串1' || ' 和 ' || '字串2';
+
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-+
| '字串1' || ' 和 ' || '字串2' |
|
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-|
| 字串1 和 字串2 |
+
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-+
PUBLIC>select concat('字串1',' 和 ','字串2');
+
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
--+
| CONCAT('字串1',' 和 ','字串2') |
|
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
--|
| 字串1 和 字串2 |
+
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
--+
如果需要包含特殊字元,可以使用 char() 函式,透過ASCII值來插入特定字元。例如,若要在輸出中顯示歐元符號,可以這樣做:
PUBLIC>select concat('我在巴黎花了 ',char(8364),'357');
+
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
---
+
| CONCAT('我在巴黎花了 ',CHAR(8364),'357') |
|
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
---
|
| 我在巴黎花了 €357 |
+
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
---
+
#### 內容解密:
此範例展示瞭如何使用 char() 函式插入特殊字元。char(8364) 傳回歐元符號(€),然後使用 concat() 將其與其他字串連線起來,形成完整的句子。
Snowflake還提供了多種函式來轉換字串的大小寫,例如轉換為全部大寫、全部小寫或每個單詞首字母大寫:
PUBLIC>select upper(str.val), lower(str.val), initcap(str.val)
from (values ('哪種大小寫最好?'))
as str(val);
+
---
-
---
-
---
-
---
-
---
--+
---
-
---
-
---
-
---
-
---
--+
---
-
---
-
---
-
---
-
---
-+
| UPPER(STR.VAL) | LOWER(STR.VAL) | INITCAP(STR.VAL) |
|
---
-
---
-
---
-
---
-
---
--+
---
-
---
-
---
-
---
-
---
--+
---
-
---
-
---
-
---
-
---
-|
| 哪種大小寫最好? | 哪種大小寫最好? | 哪種大小寫最好? |
+
---
-
---
-
---
-
---
-
---
--+
---
-
---
-
---
-
---
-
---
--+
---
-
---
-
---
-
---
-
---
-+
#### 內容解密:
upper(str.val)將輸入字串轉換為全部大寫。lower(str.val)將輸入字串轉換為全部小寫。initcap(str.val)將輸入字串的每個單詞首字母轉換為大寫。
此外,還有函式可以反轉字串的字元順序:
PUBLIC>select reverse('你能讀懂這個嗎?');
+
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-+
| REVERSE('你能讀懂這個嗎?') |
|
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-|
| ?麼嗎個這懂讀能你 |
+
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-+
#### 內容解密:
reverse() 函式將輸入的字串字元順序完全反轉。
去除字串前後空格的需求也很常見,相關函式可以幫助實作這一點。
資料操作範例
在處理資料時,經常需要進行各種轉換和操作。以下是一些常見的操作範例。
合併與更新資料
在進行資料合併時,MERGE 陳述式非常有用。例如,將 Person_Refresh 表中的資料合併到 Person 表中:
MERGE INTO person AS p
USING person_refresh AS pr
ON p.first_name = pr.fname AND p.last_name = pr.lname
WHEN MATCHED AND pr.remove = 'yes' THEN DELETE
WHEN MATCHED THEN UPDATE SET
p.birth_date = pr.dob,
p.eye_color = pr.eyes,
p.occupation = pr.profession
WHEN NOT MATCHED THEN INSERT
(first_name, last_name, birth_date, eye_color, occupation)
VALUES (pr.fname, pr.lname, pr.dob, pr.eyes, pr.profession);
#### 內容解密:
此 MERGE 陳述式根據 Person_Refresh 表更新 Person 表的資料。
- 當匹配到相同記錄且
remove欄位為 ‘yes’ 時,刪除該記錄。 - 當匹配到相同記錄時,更新相關欄位。
- 當在
Person表中找不到匹配記錄時,將新記錄插入Person表。
執行後,Snowflake會傳回插入、更新和刪除的記錄數量。