Stored procedure con Synapse SQL in Azure Synapse Analytics

I pool con provisioning e serverless di Synapse SQL consentono di inserire una logica di elaborazione dati complessa nelle stored procedure SQL. Le stored procedure sono un ottimo modo per incapsulare il codice SQL, archiviandolo vicino i dati nel data warehouse. Le stored procedure consentono agli sviluppatori di rendere modulari le soluzioni incapsulando il codice in unità gestibili, facilitando così il riutilizzo del codice stesso. Ogni stored procedure può anche accettare parametri per essere ancora più flessibile. In questo articolo sono disponibili alcuni suggerimenti per l'implementazione di stored procedure nel pool SQL di Synapse per lo sviluppo di soluzioni.

Risultati previsti

Synapse SQL supporta molte delle funzionalità T-SQL che si usano in SQL Server. Ancora più importanti sono le funzionalità di scale-out specifiche, che si possono usare per migliorare le prestazioni della soluzione. In questo articolo verranno fornite informazioni sulle funzionalità che è possibile inserire nelle stored procedure.

Nota

Nel corpo della stored procedure è possibile usare solo le funzionalità supportate nella superficie di attacco di Synapse SQL. Vedere questo articolo identificare gli oggetti, ovvero le istruzioni che si possono usare nelle stored procedure. Gli esempi in questi articoli usano funzionalità generiche disponibili sia nella superficie di attacco serverless che in quella dedicata. Vedere altre limitazioni nei pool SQL con provisioning e serverless di Synapse alla fine di questo articolo.

Per mantenere la scalabilità e le prestazioni del pool SQL sono disponibili anche funzionalità e caratteristiche con differenze di comportamento e altre che non sono supportate.

Stored procedure in Synapse SQL

Nell'esempio seguente è possibile visualizzare le stored procedure che rilasciano oggetti esterni, se presenti nel database:

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

Queste stored procedure possono essere eseguite usando l'istruzione EXEC in cui è possibile specificare il nome e i parametri della stored procedure:

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 fornisce un'implementazione semplificata e ottimizzata delle stored procedure. La differenza principale rispetto a SQL Server è che la stored procedure non è codice precompilato. Nei data warehouse il tempo di compilazione è limitato rispetto al tempo necessario per eseguire query su grandi volumi di dati. È più importante assicurarsi che il codice della stored procedure sia correttamente ottimizzato per le query di grandi dimensioni. L'obiettivo consiste nel risparmiare ore, minuti e secondi, non millisecondi. È quindi più utile pensare alle stored procedure come contenitori per la logica di SQL.

Quando Synapse SQL esegue la stored procedure, le istruzioni SQL vengono analizzate, convertite e ottimizzate in fase di esecuzione. Durante questo processo ogni istruzione viene convertita in query distribuite. Il codice SQL eseguito sui dati è diverso dalla query inviata.

Incapsulare le regole di convalida

Le stored procedure consentono di individuare la logica di convalida in un singolo modulo archiviato nel database SQL. Nell'esempio seguente è possibile osservare come convalidare i valori dei parametri e modificarne i valori predefiniti.

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

La logica nella stored procedure SQL convaliderà i parametri di input quando viene chiamata la stored procedure.


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.

Annidamento di stored procedure

Quando le stored procedure chiamano altre stored procedure o eseguono istruzioni SQL dinamiche, la stored procedure o la chiamata di codice interna è detta annidata. Un esempio di stored procedure annidata è illustrato nel codice seguente:

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

Questa stored procedure accetta un parametro che rappresenta un nome e quindi chiama altre stored procedure per eliminare gli oggetti con questo nome. Il pool SQL di Synapse supporta un massimo di otto livelli di annidamento. Questa funzionalità è leggermente diversa da SQL Server. In SQL Server i livelli di annidamento sono 32.

La chiamata di stored procedure di massimo livello equivale al livello di annidamento 1.

EXEC clean_up 'mytest'

Se la stored procedure effettua anche un'altra chiamata EXEC, il livello di annidamento aumenta a due.

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

Se la seconda routine esegue poi istruzioni in SQL dinamico, il livello di annidamento aumenterà a tre.

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

Nota

Synapse SQL attualmente non supporta @@NESTLEVEL. È necessario tenere traccia del livello di annidamento. È improbabile superare il limite di otto livelli di annidamento, ma se lo si fa, è necessario rielaborare il codice per adattare i livelli di annidamento entro tale limite.

INSERT..EXECUTE

Il pool SQL con provisioning di Synapse non consente di usare il set di risultati di una stored procedure con un'istruzione INSERT. Si può tuttavia usare un approccio alternativo. Per un esempio, vedere l'articolo sulle tabelle temporanee per i pool SQL con provisioning di Synapse.

Limiti

Esistono alcuni aspetti delle stored procedure Transact-SQL che non sono implementati in Synapse SQL, ad esempio:

Funzionalità/Opzione Sottoposto a provisioning Senza server
Stored procedure temporanee No
Stored procedure numerate No No
Stored procedure estese No No
Stored procedure CLR No No
Opzione di crittografia No
Opzione di replica No No
Parametri con valori di tabella No No
Parametri di sola lettura No No
Parametri predefiniti No
Contesti di esecuzione No No
Istruzione return No
INSERT INTO... EXEC No

Passaggi successivi

Per altri suggerimenti sullo sviluppo, vedere la panoramica dello sviluppo.