Lagrade procedurer med Synapse SQL i Azure Synapse Analytics

Med synapse SQL-etablerade och serverlösa pooler kan du placera komplex databearbetningslogik i SQL-lagrade procedurer. Lagrade procedurer är ett bra sätt att kapsla in SQL-koden och lagra den nära dina data i informationslagret. Lagrade procedurer hjälper utvecklare att modularisera sina lösningar genom att kapsla in koden i hanterbara enheter och underlätta bättre återanvändning av kod. Varje lagrad procedur kan också acceptera parametrar för att göra dem ännu mer flexibla. I den här artikeln hittar du några tips för att implementera lagrade procedurer i Synapse SQL-poolen för att utveckla lösningar.

Vad du kan förvänta dig

Synapse SQL stöder många av de T-SQL-funktioner som används i SQL Server. Ännu viktigare är att det finns utskalningsspecifika funktioner som du kan använda för att maximera lösningens prestanda. I den här artikeln får du lära dig mer om de funktioner som du kan placera i lagrade procedurer.

Anteckning

I procedurtexten kan du bara använda de funktioner som stöds i Synapse SQL-ytan. Läs den här artikeln om du vill identifiera objekt, instruktioner som kan användas i lagrade procedurer. Exemplen i dessa artiklar använder allmänna funktioner som är tillgängliga både i serverlös och dedikerad yta. Se ytterligare begränsningar i etablerade och serverlösa Synapse SQL-pooler i slutet av den här artikeln.

För att upprätthålla skalning och prestanda för SQL-pool finns det även vissa funktioner som har beteendeskillnader och andra som inte stöds.

Lagrade procedurer i Synapse SQL

I följande exempel kan du se procedurerna som släpper externa objekt om de finns i databasen:

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

Dessa procedurer kan köras med instruktionen EXEC där du kan ange procedurens namn och parametrar:

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 tillhandahåller en förenklad och strömlinjeformad implementering av lagrade procedurer. Den största skillnaden jämfört med SQL Server är att den lagrade proceduren inte är förkompilerad kod. I informationslager är kompileringstiden liten jämfört med den tid det tar att köra frågor mot stora datavolymer. Det är viktigare att se till att koden för lagrad procedur är korrekt optimerad för stora frågor. Målet är att spara timmar, minuter och sekunder, inte millisekunder. Det är därför mer användbart att tänka på lagrade procedurer som containrar för SQL-logik.

När Synapse SQL kör den lagrade proceduren parsas, översätts och optimeras SQL-uttrycken vid körning. Under den här processen konverteras varje instruktion till distribuerade frågor. SQL-koden som körs mot data skiljer sig från den fråga som skickas.

Kapsla in verifieringsregler

Med lagrade procedurer kan du hitta valideringslogik i en enda modul som lagras i SQL Database. I följande exempel kan du se hur du verifierar parametrarnas värden och ändrar deras standardvärden.

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

Logiken i SQL-proceduren validerar indataparametrarna när proceduren anropas.


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.

Kapsling av lagrade procedurer

När lagrade procedurer anropar andra lagrade procedurer, eller kör dynamisk SQL, sägs den inre lagrade proceduren eller kodanropet vara kapslat. Ett exempel på kapslad procedur visas i följande kod:

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

Den här proceduren accepterar en parameter som representerar ett visst namn och anropar sedan andra procedurer för att släppa objekten med det här namnet. Synapse SQL-poolen stöder högst åtta kapslingsnivåer. Den här funktionen skiljer sig något från SQL Server. Kapslingsnivån i SQL Server är 32.

Anropet för den lagrade proceduren på den översta nivån motsvarar kapslingsnivå 1.

EXEC clean_up 'mytest'

Om den lagrade proceduren också gör ytterligare ett EXEC-anrop ökar kapslingsnivån till två.

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

Om den andra proceduren sedan kör en dynamisk SQL ökar kapslingsnivån till 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

Anteckning

Synapse SQL stöder för närvarande inte @@NESTLEVEL. Du måste spåra kapslingsnivån. Det är osannolikt att du överskrider gränsen på åtta kapslingsnivåer, men om du gör det måste du omarbeta koden så att den passar kapslingsnivåerna inom den här gränsen.

INFOGA.. UTFÖRA

Med den etablerade Synapse SQL-poolen kan du inte använda resultatuppsättningen för en lagrad procedur med en INSERT-instruktion. Det finns en alternativ metod som du kan använda. Ett exempel finns i artikeln om temporära tabeller för etablerad Synapse SQL-pool.

Begränsningar

Det finns vissa aspekter av transact-SQL-lagrade procedurer som inte implementeras i Synapse SQL, till exempel:

Funktion/alternativ Etablerad Utan server
Tillfälligt lagrade procedurer Inga Ja
Numrerade lagrade procedurer Inga Inga
Utökade lagrade procedurer Inga Inga
LAGRADE CLR-procedurer Inga Inga
Krypteringsalternativ Inga Ja
Replikeringsalternativ Inga Inga
Tabellvärdesparametrar Inga Inga
Skrivskyddade parametrar Inga Inga
Standardparametrar Inga Ja
Körningskontexter Inga Inga
Returuttryck Inga Ja
INFOGA I .. EXEC Inga Ja

Nästa steg

Fler utvecklingstips finns i Utvecklingsöversikt.