Tip
Microsoft Fabric Data Warehouse 是一個企業規模的關聯式倉庫,建立在資料湖基礎上,具備未來準備架構、內建 AI 及新功能。 如果你是資料倉儲新手,建議先從Fabric Data Warehouse開始。 現有的 專用 SQL 工作負載可升級至 Fabric,以取得資料科學、即時分析與報告等多項新功能。
Synapse 的 SQL 配置與無伺服器池讓你能將複雜的資料處理邏輯放入 SQL 儲存程序中。 儲存程序是封裝你的 SQL 程式碼並把它存放在資料倉儲中靠近資料的好方法。 儲存程序幫助開發者模組化解決方案,將程式碼封裝成易於管理的單元,並促進程式碼的重用性。 每個儲存程序也能接受參數,使其更具彈性。 本文將提供一些在 Synapse SQL 池中實作儲存程序以開發解決方案的建議。
預期內容
Synapse SQL 支援許多 SQL Server 中使用的 T-SQL 功能。 更重要的是,有專門的擴展功能可用來最大化解決方案的效能。 在本文中,您將了解可以在儲存程序中加入哪些功能。
Note
在程序主體中,你只能使用Synapse SQL 表層區域所支援的功能。 請參閱 本文 以識別可用於儲存程序的物件或語句。 本文中的範例使用了通用特性,這些功能適用於無伺服器和專用表面區域。 本文末尾請參閱 Synapse 配置與無伺服器 SQL 池的其他限制 。
為了維持 SQL 池的規模與效能,也有一些功能與行為差異,有些則不被支援。
Synapse SQL 中的儲存程序
以下範例中,你可以看到程序如何刪除資料庫中存在的外部物件:
CREATE PROCEDURE drop_external_table_if_exists @name SYSNAME
AS BEGIN
IF (0 <> (SELECT COUNT(*) FROM sys.external_tables WHERE name = @name))
BEGIN
DECLARE @drop_stmt NVARCHAR(200) = N'DROP EXTERNAL TABLE ' + @name;
EXEC sp_executesql @tsql = @drop_stmt;
END
END
GO
CREATE PROCEDURE drop_external_file_format_if_exists @name SYSNAME
AS BEGIN
IF (0 <> (SELECT COUNT(*) FROM sys.external_file_formats WHERE name = @name))
BEGIN
DECLARE @drop_stmt NVARCHAR(200) = N'DROP EXTERNAL FILE FORMAT ' + @name;
EXEC sp_executesql @tsql = @drop_stmt;
END
END
GO
CREATE PROCEDURE drop_external_data_source_if_exists @name SYSNAME
AS BEGIN
IF (0 <> (SELECT COUNT(*) FROM sys.external_data_sources WHERE name = @name))
BEGIN
DECLARE @drop_stmt NVARCHAR(200) = N'DROP EXTERNAL DATA SOURCE ' + @name;
EXEC sp_executesql @tsql = @drop_stmt;
END
END
這些程序可用 陳述式執行 EXEC ,並指定程序名稱與參數:
EXEC drop_external_table_if_exists 'mytest';
EXEC drop_external_file_format_if_exists 'mytest';
EXEC drop_external_data_source_if_exists 'mytest';
Synapse SQL 提供簡化且精簡的儲存程序實作。 與 SQL Server 最大的不同是,儲存程序並非預先編譯的程式碼。 在資料倉儲中,編譯時間相較於對大量資料執行查詢所需的時間來說非常短。 更重要的是確保儲存程序程式碼能正確優化以應付大型查詢。 目標是節省小時、分鐘和秒數,而非毫秒。 因此,將儲存程序視為 SQL 邏輯的容器會更有幫助。
當 Synapse SQL 執行你的儲存程序時,SQL 語句會在執行時被解析、轉換並優化。 在此過程中,每個語句都被轉換成分散式查詢。 針對資料執行的 SQL 程式碼與提交的查詢不同。
封裝驗證規則
儲存程序讓你能在 SQL 資料庫中單一模組中找到驗證邏輯。 在以下範例中,你可以看到如何驗證參數值並更改其預設值。
CREATE PROCEDURE count_objects_by_date_created
@start_date DATETIME2,
@end_date DATETIME2
AS BEGIN
IF( @start_date >= GETUTCDATE() )
BEGIN
THROW 51000, 'Invalid argument @start_date. Value should be in past.', 1;
END
IF( @end_date IS NULL )
BEGIN
SET @end_date = GETUTCDATE();
END
IF( @start_date >= @end_date )
BEGIN
THROW 51000, 'Invalid argument @end_date. Value should be greater than @start_date.', 2;
END
SELECT
year = YEAR(create_date),
month = MONTH(create_date),
objects_created = COUNT(*)
FROM
sys.objects
WHERE
create_date BETWEEN @start_date AND @end_date
GROUP BY
YEAR(create_date), MONTH(create_date);
END
SQL 程序中的邏輯會在程序被呼叫時驗證輸入參數。
EXEC count_objects_by_date_created '2020-08-01', '2020-09-01'
EXEC count_objects_by_date_created '2020-08-01', NULL
EXEC count_objects_by_date_created '2020-09-01', '2020-08-01'
-- Error
-- Invalid argument @end_date. Value should be greater than @start_date.
EXEC count_objects_by_date_created '2120-09-01', NULL
-- Error
-- Invalid argument @start_date. Value should be in past.
巢狀儲存程序
當儲存程序呼叫其他儲存程序或執行動態 SQL,則內部的儲存程序或程式碼調用稱為巢狀。 巢狀程序的範例可見於以下程式碼:
CREATE PROCEDURE clean_up @name SYSNAME
AS BEGIN
EXEC drop_external_table_if_exists @name;
EXEC drop_external_file_format_if_exists @name;
EXEC drop_external_data_source_if_exists @name;
END
此程序接受代表某個名稱的參數,然後呼叫其他程序來丟棄帶有該名稱的物件。 Synapse SQL 池最多支援八個巢狀層級。 此功能與 SQL Server 略有不同。 SQL Server 的巢穴等級是 32。
頂層儲存程序呼叫等同於巢狀層級 1。
EXEC clean_up 'mytest'
如果儲存程序同時呼叫另一個 EXEC 呼叫,巢狀層級會增加到 2。
CREATE PROCEDURE clean_up @name SYSNAME
AS
EXEC drop_external_table_if_exists @name -- This call is nest level 2
GO
EXEC clean_up 'mytest' -- This call is nest level 1
如果第二個程序執行了某些動態 SQL,巢狀層級會增加到 3。
CREATE PROCEDURE drop_external_table_if_exists @name SYSNAME
AS BEGIN
/* See full code in the previous example */
EXEC sp_executesql @tsql = @drop_stmt; -- This call is nest level 3
END
GO
CREATE PROCEDURE clean_up @name SYSNAME
AS
EXEC drop_external_table_if_exists @name -- This call is nest level 2
GO
EXEC clean_up 'mytest' -- This call is nest level 1
Note
Synapse SQL 目前不支援 @@NESTLEVEL。 你需要追蹤巢穴的等級。 你不太可能超過八個巢穴等級的限制,但如果超過了,你需要重新設計程式碼,讓巢狀等級符合這個限制。
插入......執行
Provisioned Synapse SQL pool 不允許你用 INSERT 語句來消耗儲存程序的結果集。 你也可以用另一種方法。 舉例來說,請參閱有關 provisioned Synapse SQL pool 的暫存資料表文章。
局限性
Transact-SQL 儲存程序中有些面向並未用 Synapse SQL 實作,例如:
| 功能/選項 | 已佈建 | Serverless |
|---|---|---|
| 暫存儲存程序 | No | Yes |
| 有編號的預存程序 | No | No |
| 擴展預存程序 | No | No |
| CLR 儲存程序 | No | No |
| 加密選項 | No | Yes |
| 複製選項 | No | No |
| 資料表值參數 | No | No |
| 唯讀參數 | No | No |
| 預設參數 | No | Yes |
| 執行上下文 | No | No |
| 回傳敘述 | No | Yes |
| 插入...... EXEC | No | Yes |
相關內容
更多開發建議,請參閱 開發概覽。