Každá databázově řízená aplikace nakonec dosáhne bodu, kdy se SQL dotazy roztroušené v kódu aplikace stanou problémem údržby. Stejné komplexní spojení se objevuje ve třech různých službách. Obchodní logika, která patří do databázové vrstvy, proniká do aplikace. Bezpečnostní zásady, které by měly být vynucovány na datové úrovni, jsou místo toho nekonzistentně vynucovány aplikačním kódem, který lze obejít. Uložené procedury řeší tuto třídu problémů přesunem opakovaně použitelné, bezpečnostně citlivé a výkonnostně kritické SQL logiky do databáze, kde ji lze spravovat, verzovat, zabezpečit a optimalizovat nezávisle na aplikacích, které ji volají.
Uložená procedura je pojmenovaná, předkompilovaná sada příkazů SQL uložených v databázi a spouštěných jako jednotka. Přijímá parametry, obsahuje logiku a může vracet výsledky, výstupní parametry nebo stavové kódy. Na rozdíl od ad hoc dotazů odesílaných aplikačním kódem je uložená procedura analyzována a zkompilována jednou, její plán provádění je uložen do mezipaměti a znovu použit při každém dalším volání, čímž se eliminují režijní náklady na kompilaci, které vznikají při opakovaném dynamickém SQL. Tato příručka popisuje, co jsou uložené procedury, kdy je používat, jak vynucují zabezpečení, jak ovlivňují výkon a jak je spravovat, jak se z nich stávají závislosti pokrývající celou databázi.
Vymezení rozsahu každé změny databáze před jejím spuštěním
SMART TS XL mapuje závislosti uložených procedur napříč SQL, COBOL, Java a Pythonem současně.
Více informacíCo je uložená procedura?
Uložená procedura je předkompilovaná rutina uložená v relační databázi a volána jménem s volitelnými parametry. Databázový engine ji jednou zkompiluje, uloží plán spuštění do mezipaměti a znovu jej použije při každém dalším volání, čímž se vyhne cyklu parse-compile-optimalize, který ad hoc SQL dotazy vyžadují při každém spuštění.
sql
-- SQL Server: basic stored procedure
CREATE PROCEDURE GetCustomerOrders
@CustomerId INT,
@StartDate DATE,
@EndDate DATE
AS
BEGIN
SET NOCOUNT ON;
SELECT
o.OrderId,
o.OrderDate,
o.TotalAmount,
o.Status
FROM Orders o
WHERE o.CustomerId = @CustomerId
AND o.OrderDate BETWEEN @StartDate AND @EndDate
ORDER BY o.OrderDate DESC;
END;
GO
-- Calling the procedure
EXEC GetCustomerOrders
@CustomerId = 12345,
@StartDate = '2026-01-01',
@EndDate = '2026-06-30';
Aplikace nikdy nezapisuje SQL přímo. Volá GetCustomerOrders s parametry. Databáze se postará o zbytek.
Uložená procedura vs. zobrazení vs. funkce
Tři databázové objekty jsou často zaměňovány. Následující tabulka je rozlišuje:
| Objekt | Vrácení zboží | Přijímá parametry | Může upravovat data | Plán provedení uložen v mezipaměti | nejlepší |
|---|---|---|---|---|---|
| Uložené procedury | Výsledkové sady, výstupní parametry, návratové kódy | Ano | Ano | Ano | Složitá logika, operace DML, vynucování zabezpečení |
| Zobrazit | Jedna sada výsledků (jako tabulka) | Ne | Ne (obvykle) | Částečný | Zjednodušení dotazů SELECT, zabezpečení na úrovni sloupců |
| Skalární funkce | Jediná hodnota | Ano | Ne | Ne | Výpočty znovu použité v seznamech SELECT |
| Funkce s tabulkovou hodnotou | Sada výsledků | Ano | Ne | Částečný | Parametrizované pohledy, výpočty vracející množiny |
Klíčový rozdíl: Použijte zobrazení, pokud chcete opakovaně použitelnou abstrakci SELECT. Použijte uloženou proceduru, pokud potřebujete parametry, podmíněnou logiku, úpravu dat nebo vynucení zabezpečení. Použijte funkci, pokud potřebujete výpočet, který vrací hodnotu nebo tabulku a musí být sloučen s jiným SQL.
Čtyři základní výhody
Výkon: Předkompilace a ukládání plánů do mezipaměti
Když SQL Server, PostgreSQL nebo Oracle přijme volání uložené procedury, zkontroluje, zda pro danou proceduru existuje plán spuštění uložený v mezipaměti. Pokud ano, provede se okamžitě. Pokud ne, proceduru zkompiluje, vygeneruje plán spuštění, uloží ho do mezipaměti a provede se. Při všech následujících voláních se plán uložený v mezipaměti znovu použije.
Ad hoc SQL dotazy, zřetězené dotazy odesílané z aplikačního kódu, mohou být při každém volání znovu kompilovány v závislosti na databázi a struktuře dotazu. U dotazů s vysokou frekvencí volaných tisíckrát za sekundu je tato kompilační režie značná.
sql
-- Demonstrating plan reuse in SQL Server
-- Check if a plan exists for a procedure
SELECT
qs.execution_count,
qs.total_elapsed_time / qs.execution_count AS avg_elapsed_ms,
qs.total_logical_reads / qs.execution_count AS avg_logical_reads,
SUBSTRING(qt.text, 1, 100) AS procedure_text
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
WHERE qt.text LIKE '%GetCustomerOrders%'
ORDER BY qs.execution_count DESC;
Druhou výhodou z hlediska výkonu je snížení síťového provozu . Místo odesílání složitého 30řádkového SQL dotazu z aplikace do databáze při každém volání odesílá aplikace volání krátké procedury. Síťové zatížení je minimální. Databáze provádí náročné výpočty na straně serveru a vrací pouze sadu výsledků.
Zabezpečení: Omezení přímého přístupu k tabulce
Toto je výhoda, kterou SC data konkrétně hledají, „jak používat uložené procedury k omezení přímého přístupu k datům a zvýšení zabezpečení databáze.“ Mechanismus je přímočarý a výkonný.
Udělit uživatelům aplikace oprávnění ke spouštění uložených procedur. Odepřít přímý přístup k podkladovým tabulkám. Uživatel může proceduru volat, ale nemůže se přímo dotazovat, vkládat, aktualizovat ani mazat z tabulky.
sql
-- Create a role for application users
CREATE ROLE AppReadRole;
-- Grant execute on the procedure
GRANT EXECUTE ON GetCustomerOrders TO AppReadRole;
-- Deny direct table access
DENY SELECT ON Orders TO AppReadRole;
DENY SELECT ON Customers TO AppReadRole;
-- The user can now:
-- EXEC GetCustomerOrders @CustomerId=123, ... -> works
-- SELECT * FROM Orders WHERE ... -> ACCESS DENIED
Druhou bezpečnostní výhodou je prevence SQL injection . Uložené procedury, které používají parametrizované vstupy namísto dynamické konstrukce SQL, jsou ze své podstaty chráněny proti SQL injection. Hodnota parametru je považována za literál, nikoli za kód SQL.
sql
-- VULNERABLE: dynamic SQL built from user input
DECLARE @sql NVARCHAR(500);
SET @sql = 'SELECT * FROM Customers WHERE Name = ''' + @UserInput + '''';
EXEC(@sql);
-- An attacker can inject: '; DROP TABLE Customers; --
-- SAFE: parameterized stored procedure
CREATE PROCEDURE GetCustomerByName
@CustomerName NVARCHAR(100)
AS
BEGIN
SELECT CustomerId, Name, Email
FROM Customers
WHERE Name = @CustomerName; -- @CustomerName is a literal, not SQL
END;
Dávej si pozor: Uložená procedura, která interně vytváří dynamický SQL pomocí
EXEC()orsp_executesqlZřetězení řetězců uživatelských vstupů je stejně zranitelné jako dynamický SQL na úrovni aplikace. Parametrizace se musí vztahovat na jakýkoli dynamický SQL vytvořený uvnitř procedury.
Údržba: Jedna změna, všechny aplikace aktualizovány
Když se změní obchodní logika, pravidla pro výpočet daní, úrovně slev, transformace dat vyžadované pro dodržování předpisů, uložená procedura centralizuje tuto logiku na jednom místě. Každá aplikace, která proceduru volá, automaticky obdrží aktualizované chování, aniž by bylo nutné ji znovu nasadit.
sql
-- Before: discount logic duplicated in three application services
-- After: centralized in one stored procedure
CREATE PROCEDURE CalculateOrderTotal
@OrderId INT,
@DiscountedTotal DECIMAL(10,2) OUTPUT
AS
BEGIN
DECLARE @Subtotal DECIMAL(10,2);
DECLARE @CustomerTier NCHAR(1);
SELECT @Subtotal = SUM(li.Quantity * li.UnitPrice),
@CustomerTier = c.Tier
FROM OrderLineItems li
JOIN Orders o ON o.OrderId = li.OrderId
JOIN Customers c ON c.CustomerId = o.CustomerId
WHERE li.OrderId = @OrderId
GROUP BY c.Tier;
-- Business rule: Gold customers get 15%, Silver get 8%, Standard get 0%
SET @DiscountedTotal = @Subtotal * CASE @CustomerTier
WHEN 'G' THEN 0.85
WHEN 'S' THEN 0.92
ELSE 1.00
END;
END;
Změňte procenta slev na jednom místě. Všechny tři aplikační služby, které volají CalculateOrderTotal okamžitě odrážet nové sazby.
Zapouzdření s výstupními parametry a ošetření chyb
Uložené procedury vracejí více hodnot prostřednictvím výstupních parametrů a sdělují stav zpracování prostřednictvím návratových kódů, což umožňuje bohatší interakční vzorce než jednoduchý SELECT.
sql
CREATE PROCEDURE InsertOrder
@CustomerId INT,
@OrderDate DATE,
@NewOrderId INT OUTPUT,
@StatusCode INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION;
INSERT INTO Orders (CustomerId, OrderDate, Status)
VALUES (@CustomerId, @OrderDate, 'PENDING');
SET @NewOrderId = SCOPE_IDENTITY();
SET @StatusCode = 0; -- success
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
SET @StatusCode = ERROR_NUMBER();
SET @NewOrderId = -1;
END CATCH;
END;
-- Usage
DECLARE @OrderId INT, @Status INT;
EXEC InsertOrder
@CustomerId = 5001,
@OrderDate = '2026-07-15',
@NewOrderId = @OrderId OUTPUT,
@StatusCode = @Status OUTPUT;
IF @Status <> 0
PRINT 'Insert failed with error: ' + CAST(@Status AS VARCHAR);
ELSE
PRINT 'Created order: ' + CAST(@OrderId AS VARCHAR);
Optimalizace výkonu: Co vám říká plán provedení
Plán provedení je záznam databázového enginu o tom, jak se rozhodl provést dotaz, jaké indexy použil, jaký algoritmus spojení zvolil a kolik řádků odhadl v každém kroku. U uložené procedury volané tisíckrát denně je plán provedení primárním diagnostickým nástrojem pro problémy s výkonem.
sql
-- Enable actual execution plan in SQL Server
-- Then run:
EXEC GetCustomerOrders
@CustomerId = 12345,
@StartDate = '2026-01-01',
@EndDate = '2026-06-30';
-- Check for parameter sniffing issues
-- (cached plan was optimized for a different parameter distribution)
EXEC GetCustomerOrders
@CustomerId = 99999, -- rare customer with very few orders
@StartDate = '2026-01-01',
@EndDate = '2026-06-30'
WITH RECOMPILE; -- forces fresh plan for this call
Čmuchání parametrů je nejčastějším problémem s výkonem uložených procedur. SQL Server ukládá do mezipaměti plán spuštění vygenerovaný pro první sadu parametrů, se kterými je procedura volána. Pokud následná volání používají velmi odlišné hodnoty parametrů, například zákazník s 50 000 objednávkami oproti zákazníkovi se 2 objednávkami, může být plán uložený v mezipaměti pro tyto hodnoty velmi neoptimální.
Strategie zmírňování: OPTIMIZE FOR nápověda k optimalizaci pro reprezentativní hodnotu parametru; WITH RECOMPILE na úrovni procedury pro generování nového plánu při každém volání (nákladné, ale efektivní, když se distribuce parametrů značně liší); přiřazení lokálních proměnných na začátku procedury pro zabránění „sniffingu“:
sql
CREATE PROCEDURE GetCustomerOrders
@CustomerId INT,
@StartDate DATE,
@EndDate DATE
AS
BEGIN
-- Local variable trick: prevents parameter sniffing
DECLARE @LocalCustomerId INT = @CustomerId;
DECLARE @LocalStart DATE = @StartDate;
DECLARE @LocalEnd DATE = @EndDate;
SELECT o.OrderId, o.OrderDate, o.TotalAmount
FROM Orders o
WHERE o.CustomerId = @LocalCustomerId
AND o.OrderDate BETWEEN @LocalStart AND @LocalEnd;
END;
Nejlepší postupy: Pracovní kontrolní seznam
Spíše než obecné principy se jedná o postupy, které umožňují udržovat uložené procedury ve velkém měřítku:
Pojmenování a organizace
- Používejte konzistentní konvenci pojmenování:
usp_prefix pro uživatelské uložené procedury,sp_vyhrazeno pro systémové procedury - Pojmenujte procedury pomocí slovesa + podstatného jména:
GetCustomerOrders,InsertPaymentRecord,UpdateInventoryCount - Seskupení souvisejících procedur ve schématu:
Sales.GetCustomerOrders,Inventory.UpdateStock
Struktura kódu
- Začněte každý postup s
SET NOCOUNT ONpotlačit zprávy o počtu řádků, které by klienti mohli špatně interpretovat - Použijte
BEGIN TRY / BEGIN CATCHbloky s explicitnímBEGIN TRANSACTION / COMMIT / ROLLBACK - Vyhněte se kurzorům pro operace s množinami, pokud možno přepište SQL jako SQL založené na množinách
- Nepoužívejte
SELECT *, pojmenujte každý sloupec, který procedura vrací
Bezpečnost
- Udělit procedurám oprávnění ke spuštění; zakázat aplikačním rolím přímý přístup k tabulce
- Vyhněte se dynamickému SQL sestavování z uživatelského vstupu uvnitř procedur
- Použijte
sp_executesqls parametrizovanými dotazy, pokud je dynamické SQL nevyhnutelné
Výkon
- Zkontrolujte plány provádění pro skenování tabulek u velkých tabulek, v případě potřeby přidejte indexy.
- Test s reprezentativními hodnotami parametrů pro postupy náchylné k „sniffingu“
- monitor
sys.dm_exec_procedure_statspro postupy s vysokou mírou provedení nebo vysokou dobou trvání
Dokumentace
- Přidejte do každé procedury komentář v záhlaví: účel, parametry, návratové hodnoty, autor, poslední úprava
- Dokumentujte obchodní pravidla zakódovaná v logice procedury, nejen co SQL dělá, ale i proč
Správa závislostí uložených procedur
Uložené procedury neexistují izolovaně. Procedura, která čte z pěti tabulek, volá dvě další procedury a je volána tuctem aplikačních služeb, je komponenta se složitými závislostmi ve všech třech směrech: na čem závisí, co závisí na ní a co sdílí s ostatními procedurami.
Když se změní typ sloupce tabulky, je třeba otestovat každou proceduru, která na tento sloupec odkazuje. Když se změní výstupní formát procedury, je třeba validovat každého volajícího. Pokud se procedura zvažuje k úpravě, rozsah změny a požadované regresní testování určuje celá sada volajících procedur.
Typy závislostí, na kterých záleží:
- Závislosti objektů: tabulky, pohledy, funkce a další procedury, na které procedura odkazuje
- Závislosti volajícího: kód aplikace, další uložené procedury a naplánované úlohy, které volají tuto proceduru
- Závislosti schématu: tabulky a definice sloupců, kterým se musí shodovat typy parametrů procedury a seznamy SELECT
- Závislosti transakcí: procedury, které sdílejí rozsah transakce se svými volajícími nebo mezi sebou navzájem
V malé databázi s deseti uloženými procedurami lze tyto závislosti sledovat ručně. V databázovém komplexu se stovkami uložených procedur, což je běžné v podnikových prostředích, kde uložené procedury zapouzdřují roky obchodní logiky, vede ruční sledování závislostí k neúplným mapám a incidentům souvisejícím se změnami.
Jak SMART TS XL Spravuje závislosti uložených procedur v podnikovém měřítku
SMART TS XLJe statická analýza kódu Analyzuje uložené procedury SQL spolu s programy v COBOLu, službami Java, pipelinemi Pythonu a dalšími komponentami, které interagují se stejnou databází. Sjednocená analýza vytváří strukturální model napříč jazyky: nejen závislosti SQL-SQL v rámci databáze, ale celý řetězec od kódu aplikace přes uložené procedury až po podkladové tabulky a zpět.
Funkce mapování závislostí aplikací vytváří kompletní graf volajících: které programy v COBOLu používají vestavěný SQL, který čte z tabulek vlastněných uloženými procedurami, které služby Java volají uložené procedury prostřednictvím JDBC, které dávkové úlohy JCL volají databázové nástroje, které spouštějí uložené procedury. Když se změní signatura nebo chování uložené procedury, mapa závislostí zobrazuje každého volajícího v každém jazyce a kompletní rozsah toho, co je třeba otestovat, než se změna dostane do produkčního prostředí.
Jedno analýza dopadu Díky této mapě závislostí lze tuto mapu využít pro plánování změn: navrhnout změnu CalculateOrderTotal a obdržet výčtový seznam všech komponent, které ji volá, všech tabulek, které čte a do kterých zapisuje, a všech následných procedur, které vyvolá. Tím se otázka „co tohle rozbije?“ přemění z cvičení v kmenových znalostech na strukturovanou, na důkazech založenou zprávu o rozsahu.
Jedno podnikové vyhledávání schopnost umožňuje dotazování na celý model závislostí: najít každou uloženou proceduru, která čte z Orders, každý volající GetCustomerOrders, každá procedura, která během několika sekund upraví konkrétní sloupec v databázovém majetku libovolné velikosti.
Pro týmy provádějící starší modernizace programy, kde uložené procedury kódují desítky let obchodní logiky, která musí být během migrace zachována, SMART TS XLAnalýza poskytuje strukturální dokumentaci, která umožňuje extrahovat logiku a plánovat migrační sekvenci.
Databázová vrstva, která si zaslouží své udržení
Uložené procedury nejsou pozůstatkem dřívější éry databází. Jsou tím správným místem pro logiku, která do databáze patří: vynucování zabezpečení, které musí být konzistentní bez ohledu na to, která aplikace k datům přistupuje, dotazy citlivé na výkon, které těží z plánů provádění uložených v mezipaměti, a obchodní pravidla, která by se měla aktualizovat jednou a šířit všude.
Pastí nespočívá v používání uložených procedur, ale v jejich rozrůstání do nedokumentované, nemapované sítě závislostí, které nikdo plně nerozumí. Uložená procedura, která provádí kritické obchodní výpočty, ale nemá žádné zdokumentované volající, žádný komentář v záhlaví vysvětlující její účel a žádnou analýzu dopadu před úpravou, je zátěží bez ohledu na to, jak dobře byla napsána. Správa grafu závislostí je stejně důležitá jako správa samotného SQL. Obojí vyžaduje spíše systematickou analýzu než kmenové znalosti.