Historisch gezien waren de taken van dynamische rapporten met een variabel aantal groeperingen niet voorzien door de SQL-standaard — het was ontworpen voor statisch gedefinieerde query's met een duidelijk gedefinieerde resultaatstructuur. Met de opkomst van BI-platforms en interactieve dashboards zijn programmeurs gaan zoeken naar manieren om SQL-query's "on-the-fly" te construeren, zodat ze op verzoek van de gebruiker complexe meervoudige data-slices kunnen genereren.
Probleem — Je kunt SQL niet programmeren met gebruikelijke if/else-logic binnen SELECT — het aantal kolommen, de velden zelf en zelfs GROUP BY worden alleen in de compilatiefase van de query bepaald. Als de gebruiker een slice van meerdere willekeurige velden wenst, moet je de query-tekst dynamisch samenstellen en deze uitvoeren via EXECUTE/Dynamic SQL.
Oplossing:
Generatie van SQL-code wordt uitgevoerd in een externe applicatie met een daaropvolgende oproep via EXEC/EXECUTE. In sommige gevallen voor eenvoudige taken worden CASE en rigide sjablonen gebruikt, maar voor flexibiliteit wordt altijd gebruikgemaakt van dynamische SQL:
Voorbeeldcode (Pseudocode):
-- Aan de kant van de applicatie (bijvoorbeeld, Python) groups = ['region', 'channel', 'month'] columns = [f'SUM({col}) AS {col}_sum' for col in selected_metrics] group_by = ', '.join(groups) selects = ', '.join(groups + columns) query = f'SELECT {selects} FROM sales GROUP BY {group_by}' -- Vervolgens wordt deze query verzonden via de application/sql-interface
In een DBMS die EXECUTE ondersteunt:
DECLARE @sql NVARCHAR(MAX); SET @sql = N'SELECT ' + @selects + ' FROM sales GROUP BY ' + @group_by + ';'; EXEC sp_executesql @sql;
Belangrijke kenmerken:
Kan het dynamisch wijzigen van het aantal kolommen (pivot/unpivot) alleen worden gedaan via standaard SELECT zonder dynamische SQL?
Nee — alleen vooraf bekende waarden kunnen "uitgeklapt" worden via CASE/DECODE, maar een onbekend aantal kolommen wordt alleen dynamisch bereikt.
Garandeert je logica voor dynamische SQL bescherming tegen injecties, als je string concatenation gebruikt?
Nee, handmatige stringconcatenatie is een constante risico voor SQL-injectie. Het is noodzakelijk om de lijst met velden/groeperingen te valideren door whitelisting, gebruikersfragmenten zonder controle te vermijden, en nog beter om parameters te gebruiken waar mogelijk.
Kan GROUP BY een lijst met kolommen via een variabele accepteren?
Standaard SQL ondersteunt het doorgeven van een lijst velden in GROUP BY via een variabele/parameter niet. De tekst van de query moet dynamisch worden samengesteld — simpelweg een variabele in de lijst GROUP BY gebruiken is niet mogelijk.
Een BI-engineer stond de gebruiker toe om rechtstreeks vanuit de applicatie-interface veldnamen voor het rapport door te geven — zonder ze te filteren via whitelisting. Hierdoor werd bij het testen van injecties de productie-tabel "neergehaald" door ingevoegde schadelijke code in de veldnaam.
Voordelen:
Nadelen:
De engineer implementeerde strikte validatie van namen — de gebruiker kon alleen kiezen uit toegestane kolommen (uit config/metadata), dynamische SQL werd alleen opgebouwd via whitelisting, er waren geen paden voor injectie.
Voordelen:
Nadelen: