📖 Srce Programabilnosti
Stored Procedura (SP) nije samo kolekcija SQL naredbi. To je programski modul sačuvan unutar baze koji može prihvatati parametre, izvršavati grananja (IF/ELSE), petlje (WHILE) i vraćati rezultate aplikaciji. One su ključne za performanse jer SQL Server čuva njihov Execution Plan u memoriji.
📥 Parametri: Više od običnih varijabli
1. OUTPUT Parametri
Koristimo ih kada želimo vratiti jednu ili više specifičnih vrijednosti bez vraćanja cijelog result-seta.
2. Table-Valued Parameters (TVP)
Ovo je revolucija u komunikaciji Aplikacija-Baza. TVP vam omogućava da pošaljete hiljade redova u SP kao jedan parametar, umjesto da pozivate bazu hiljadu puta.
-- 1. Definisanje "Tipa Tabele"
CREATE TYPE Stats.ReportDataType AS TABLE (
DataType NVARCHAR(50),
Value DECIMAL(18,2),
RegionID INT,
Year INT
);
GO
-- 2. Korištenje tipa u proceduri (READONLY je obavezan)
CREATE PROCEDURE Stats.usp_BulkInsertReportData
@ReportID INT,
@DataItems Stats.ReportDataType READONLY
AS
BEGIN
INSERT INTO Stats.ReportData (ReportID, DataType, Value, RegionID, Year)
SELECT @ReportID, DataType, Value, RegionID, Year FROM @DataItems;
END;
GO
🛡️ Robusno Rukovanje Greškama
U profesionalnom kodu ne koristimo staru @@ERROR varijablu. Koristimo
TRY...CATCH blokove i THROW naredbu.
⚠️ Zašto XACT_ABORT ON?
Uvijek podesite SET XACT_ABORT ON na početku procedure. Ovo osigurava da SQL Server
automatski prekine i poništi (Rollback) cijelu transakciju ako se desi bilo kakva greška,
sprečavajući "djelimično upisane" podatke.
CREATE PROCEDURE dbo.SafeUpdate
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON; -- Vitalni dio!
BEGIN TRY
BEGIN TRANSACTION
-- Vaš SQL kod ovdje
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
-- Logiranje greške u posebnu tabelu (opcionalno)
-- Ponovno bacanje greške aplikaciji
THROW;
END CATCH
END;
🚀 Performance Tuning: Parameter Sniffing
Parameter Sniffing se dešava kada SQL Server kreira plan izvršenja prilagođen PRVOM parametru koji je poslan u SP. Ako je sljedeći parametar drastično drugačiji (npr. traži 1 rekord naspram 1 milion), plan će biti užasno neefikasan.
💡 Kako popraviti?
- Koristite
OPTIMIZE FOR UNKNOWNna kraju upita. - Koristite lokalne varijable unutar procedure.
- Dodajte
WITH RECOMPILEako se podaci drastično mijenjaju svaki put.
🎯 Praktična Vježba: Kompleksni Workflow
Zadatak: Kreiranje Izvještaja sa Provjerom Budžeta
Morate napisati proceduru koja prima DepartmentID i TVP sa listom podataka. Procedura mora: 1. Provjeriti da li odjeljenje ima dovoljno budžeta za izvještaj. 2. Ako nema, baciti user-friendly grešku. 3. Ako ima, kreirati izvještaj i dodati podatke (sve u transakciji).
CREATE PROCEDURE Stats.usp_CreateReport
@DepartmentID INT,
@CreatedBy INT,
@ReportName NVARCHAR(200),
@ReportType NVARCHAR(50),
@ReportData Stats.ReportDataType READONLY
AS
BEGIN
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION
-- Provjera budžeta odjeljenja
DECLARE @DepartmentBudget DECIMAL(15,2);
SELECT @DepartmentBudget = Budget FROM Stats.Departments WHERE DepartmentID = @DepartmentID;
IF @DepartmentBudget < 10000 -- Minimalni budžet za izvještaj
THROW 50001, 'Odjeljenje nema dovoljno budžeta za kreiranje izvještaja.', 1;
-- Kreiranje izvještaja
DECLARE @NewReportID INT;
INSERT INTO Stats.Reports (ReportName, DepartmentID, CreatedBy, ReportType, Status)
VALUES (@ReportName, @DepartmentID, @CreatedBy, @ReportType, 'Draft');
SET @NewReportID = SCOPE_IDENTITY();
-- Dodavanje podataka izvještaja
INSERT INTO Stats.ReportData (ReportID, DataType, Value, RegionID, Year)
SELECT @NewReportID, DataType, Value, RegionID, Year FROM @ReportData;
COMMIT TRANSACTION
END TRY
BEGIN CATCH
THROW;
END CATCH
END;
✅ Zaključak
Stored procedure su vaša prva linija odbrane:
- ✅ TVP smanjuje broj poziva bazi sa 1000 na 1.
- ✅ TRY/CATCH sa XACT_ABORT osigurava integritet.
- ✅ Razumijevanje Parameter Sniffing-a rješava 80% misterioznih usporavanja baze.
📚 Sljedeća Lekcija
U Lekciji 3.3 prelazimo na Funkcije (UDF). Naučićete razliku između Scalar i Table-Valued funkcija i zašto su one zloglasne po pitanju performansi ako ih pogrešno koristite.