Dynamisk SQL og lagrede procedurer er to af de vigtigste komponenter i SQL Server. I denne artikel vil vi se på fordele og ulemper ved hver af dem, og hvornår de skal bruges.
Ydeevne
Alle kender svaret på dette spørgsmål. Lagrede procedurer slår dynamisk SQL med hensyn til ydeevne. En lagret procedure er cachelagret i serverhukommelsen, og dens udførelse er meget hurtigere end dynamisk SQL. Hvis alle de resterende variable holdes konstante, overgår den lagrede procedure dynamisk SQL.
Adskillelse af bekymringer
Med hensyn til adskillelse af bekymringer slår lagrede procedurer dynamisk SQL uden problemer.
Lagrede procedurer giver dig mulighed for at holde din databaselogik adskilt fra din forretningslogik. Hvis der opstår en fejl i din forretningslogik, skal du derfor kun ændre din ansøgningskode. Omvendt, hvis der er et problem med din databaselogik, er det kun din lagrede procedure, der skal ændres. Desuden, hvis en lagret procedure opdateres, behøver applikationskoden ikke at blive genkompileret og implementeret.
Hvis du bruger dynamiske SQL-forespørgsler i din klientkode, skal du opdatere applikationskoden, hvis der opstår en fejl i SQL-forespørgslen. Det betyder, at du bliver nødt til at omkompilere og implementere applikationskoden.
Netværkstrafik
Lagrede procedurer producerer mindre netværkstrafik end dynamisk SQL, fordi udførelse af en lagret procedure kun kræver, at procedurenavnet og parametrene (hvis nogen) sendes over netværket.
Udførelse af dynamisk SQL kræver, at hele forespørgslen sendes på tværs af netværket, hvilket øger netværkstrafikken, især hvis forespørgslen er meget stor.
SQL-injektionsangreb
Lagrede procedurer er ikke sårbare over for SQL Injection-angreb.
Dynamiske SQL-forespørgsler er sårbare over for SQL-injektionsangreb, hvis parameteriserede forespørgsler ikke bruges, og parameteriserede forespørgsler kan ikke bruges med dynamisk SQL, hvis et tabel- eller kolonnenavn videregives som en parameter.
I dette tilfælde er løsningen, at kodenavnsfunktionen kan bruges til at forhindre SQL-injektionsangreb.
Genbrugbarhed af cachelagrede forespørgselsplaner
Lagrede procedurer forbedrer databasens ydeevne, da de tillader, at cachelagrede forespørgselsplaner kan genbruges. I tilfælde af dynamisk SQL bliver du nødt til at bruge parametriserede forespørgsler for at øge den cachelagrede forespørgselsplans genanvendelighed. I mangel af parametriserede forespørgselsplaner, registrerer SQL-serveren automatisk parametre og genererer cachelagrede forespørgselsplaner, hvilket resulterer i forbedret ydeevne.
Det er relevant at nævne her, at det kun er OLTP-systemer, der nyder godt af genbrugbarheden af cachede forespørgselsplaner. I tilfælde af OLAP-systemer, valget af optimering ændres, OLAP-systemet drager fordel af den unikke plan.
Vedligeholdelse
Lagrede procedurer med statisk SQL er nemmere at vedligeholde. For eksempel, i tilfælde af statisk SQL i en lagret procedure, kan syntaksfejl fanges, før de køres. I tilfælde af dynamisk SQL inde i lagrede procedurer kan syntaksfejl ikke fanges før forespørgslen udføres.
Desuden er lagrede procedurer mere som funktioner, de defineres én gang og kan derefter kaldes hvor som helst i scriptet. Derfor, hvis du ønsker at opdatere en lagret procedure, skal du kun opdatere den ét sted. Alle applikationsdele, der kalder den lagrede procedure, vil have adgang til den opdaterede version. En ulempe er dog, at disse applikationsdele også kan blive påvirket, hvor du ikke ønsker den opdaterede lagrede procedure. I tilfælde af dynamisk SQL skal du muligvis skrive SQL-script flere steder, men i sådanne tilfælde påvirker opdatering af script det ene sted ikke det andet. En beslutning mellem at bruge en lagret procedure og dynamisk SQL afhænger af applikationens funktionalitet.
Sikkerhed
Hvis flere applikationer får adgang til databasen, er det mere sikkert at bruge lagrede procedurer end dynamisk SQL.
Lagrede procedurer giver et ekstra lag af sikkerhed, hvorimod brugerkonteksten er den eneste måde at kontrollere tilladelser på dynamiske SQL-scripts. Alt i alt er det besværligt at sikre dynamisk SQL sammenlignet med lagrede procedurer.
Identifikation af afhængigheder
I en relationsdatabase har tabeller afhængigheder af andre tabeller i databasen.
Overvej et scenario, hvor du vil fjerne en tabel, men før du gør det, vil du finde ud af alle tabelafhængigheder. Eller i enkle vendinger, du vil finde de forespørgsler, der får adgang til den tabel, du vil slette. I disse tilfælde kan du bruge sp_depends lagrede procedure.
Sp_depends kan dog kun detektere de afhængigheder, hvor statisk SQL bruges i en lagret procedure. I tilfælde af, at dynamisk SQL er afhængig af en tabel, kan denne afhængighed ikke detekteres af den lagrede sp_depends-procedure. Lad os se dette i aktion ved hjælp af et simpelt eksempel.
Forberedelse af dummy-data
Lad os oprette nogle dummy-data for at hjælpe med at forklare begrebet afhængigheder i statisk og dynamisk SQL.
CREATE DATABASE deptest; USE deptest CREATE TABLE student ( Id int identity primary key, Name VARCHAR(50) NOT NULL, Gender VARCHAR(50) NOT NULL, Age int ) INSERT INTO student VALUES ('James', 'Male', 20), ('Helene', 'Female', 20), ('Sofia', 'Female', 20), ('Ed', 'Male', 20), ('Ron', 'Female', 20)
Nu har vi en testdatabase, der indeholder en tabel og nogle testdata. Lad os nu oprette to lagrede procedurer, der får adgang til elevtabellen.
Den første lagrede procedure bruger statisk SQL til at hente alle posterne fra elevtabellen:
USE deptest GO CREATE PROC spStatProc AS BEGIN SELECT * FROM student END
Udfør scriptet ovenfor. Dette script opretter en lagret procedure "spStatProc" i den depteste database.
Lad os oprette en anden lagret procedure, der indeholder dynamisk SQL, som henter alle posterne fra elevtabellen.
USE deptest GO CREATE PROC spDynProc AS BEGIN DECLARE @query NVARCHAR(100) SET @query = 'SELECT * FROM student' EXECUTE sp_execute @query END
Dette script opretter en lagret procedure "spDynProc" inde i den depteste database. Denne lagrede procedure bruger en dynamisk SQL-sætning til at hente alle posterne fra elevtabellen.
Nu har vi to lagrede procedurer, der er afhængige af elevbordet. En af dem indeholder statisk SQL, og den anden indeholder dynamisk SQL.
Men hvis du udfører den lagrede sp_depends-procedure og sender den til elevtabellen som en parameter, vil du se, at den kun vil hente den "spStatProc"-lagrede procedure. Dette er fordi det indeholder statisk SQL. Den "spDynProc" lagrede procedure vil blive ignoreret, da den indeholder dynamisk SQL.
Udfør følgende script.
USE deptest GO EXECUTE sp_depends student
Det vil få følgende output:
[tabel id=40 /]
Du kan se, at sp_depends ikke var i stand til at rapportere "spDynProc"-afhængigheden og kun rapporterede "spStatProc".
Kompleksitet
Lagrede procedurer kan blive ekstremt komplekse, hvis du bruger et stort antal filtre, og der er flere AND- og OR-klausuler mellem filtrene. På den anden side kan du ved hjælp af dynamisk SQL dynamisk generere WHERE-klausuler afhængigt af typen af filtre. Dette gør dynamisk SQL til det bedre valg, hvis du vil implementere ekstremt kompleks logik.
Konklusion
Samlet set overgår den lagrede procedure dynamisk SQL i næsten alle aspekter. De er hurtigere, sikre og nemme at vedligeholde og kræver mindre netværkstrafik. Som en tommelfingerregel bør lagrede procedurer bruges i scenarier, hvor du ikke behøver at ændre dine forespørgsler, og dine forespørgsler ikke er særlig komplekse. Men hvis du ofte ændrer tabelnavne, kolonnenavne eller antallet af parametre i din forespørgsel, er Dynamic SQL det bedre valg på grund af dens enklere implementeringsstrategi.
Nyttige links
- Dynamisk SQL versus lagrede procedurer
- Frygt ikke Dynamisk SQL
- Opbygning af højtydende lagrede procedurer
- Kurser om lagrede procedurer