共用方式為


在 Azure Synapse Analytics 中使用 Synapse SQL 的預存程序

Synapse SQL 已佈建和無伺服器的集區,可讓您將複雜的資料處理邏輯放入 SQL 的預存程序中。 預存程序很適合用來封裝您的 SQL 程式碼,並在資料倉儲中將其儲存至您的資料附近。 預存程序會將程式碼封裝成可管理的單位,藉此協助開發人員將其解決方案模組化,並提升程式碼的可重複使用性。 每個預存程序也可接受參數,使其更具彈性。 在本文中,您將了解一些在 Synapse SQL 集區中執行預存程序來開發解決方案的秘訣。

預期的情況

Synapse SQL 支援許多 SQL Server 中使用的 T-SQL 功能。 更重要的是有相應放大的特定功能,您可用來將解決方案效能最大化。 在本文中,您將了解可放置在預存程序中的功能。

注意

在程序主體中,您只能使用 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 呼叫,這會將巢狀層級提高到二。

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,巢狀層級會提高到三。

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

注意

Synapse SQL 目前不支援 @@NESTLEVEL。 您需要追蹤巢狀層級。 您不太可能會超過八個巢狀層級限制,但如果會,則需要修改您的程式碼,以讓巢狀層級符合這項限制。

INSERT..EXECUTE

已佈建的 Synapse SQL 集區不允許您透過 INSERT 陳述式取用預存程序的結果集。 您可以使用另一個方法。 如需範例,請參閱已佈建 Synapse SQL 集區暫存資料表上的文章。

限制

在 Synapse SQL 中不會實作 TRANSACT-SQL 預存程序的部分層面,例如:

功能/選項 已佈建 無伺服器
暫存預存程序
編號的預存程序
擴充預存程序
CLR 預存程序
加密選項
複寫選項
資料表值參數
唯讀參數
預設參數
執行內容
Return 陳述式
INSERT INTO .. EXEC

後續步驟

如需更多開發秘訣,請參閱開發概觀