sql >> Database >  >> RDS >> Sqlserver

Variabelen samenvoegen tot SQL-strings

U kunt dit bereiken (als ik begrijp wat u probeert te doen) met behulp van dynamische SQL.

De truc is dat je een string moet maken die de SQL-instructie bevat. Dat komt omdat de tabelnaam moet worden opgegeven in de eigenlijke SQL-tekst, wanneer u de instructie uitvoert. De tabelverwijzingen en kolomverwijzingen kunnen niet als parameters worden aangeleverd, die moeten in de SQL-tekst voorkomen.

U kunt dus zoiets als deze benadering gebruiken:

SET @stmt = 'INSERT INTO @tmpTbl1 SELECT ' + @KeyValue 
    + ' AS fld1 FROM tbl' + @KeyValue

EXEC (@stmt)

Eerst maken we een SQL-statement als een string. Gegeven een @KeyValue van 'Foo', zou dat een string creëren met:

'INSERT INTO @tmpTbl1 SELECT Foo AS fld1 FROM tblFoo'

Op dit moment is het gewoon een string. Maar we kunnen de inhoud van de string uitvoeren, als een dynamische SQL-instructie, met behulp van EXECUTE (of EXEC in het kort).

De ouderwetse sp_executesql procedure is een alternatief voor EXEC, een andere manier om dynamische SQL uit te voeren, waarmee u ook parameters kunt doorgeven, in plaats van alle waarden als letterlijke waarden in de tekst van de instructie op te geven.

VERVOLG

EBarr wijst erop (juist en belangrijk) dat deze aanpak vatbaar is voor SQL-injectie.

Bedenk wat er zou gebeuren als @KeyValue bevatte de string:

'1 AS foo; DROP TABLE students; -- '

De tekenreeks die we zouden produceren als een SQL-instructie zou zijn:

'INSERT INTO @tmpTbl1 SELECT 1 AS foo; DROP TABLE students; -- AS fld1 ...'

Wanneer we die string UITVOEREN als een SQL-instructie:

INSERT INTO @tmpTbl1 SELECT 1 AS foo;
DROP TABLE students;
-- AS fld1 FROM tbl1 AS foo; DROP ...

En het is niet zomaar een DROP TABLE die kan worden geïnjecteerd. Elke SQL kan worden geïnjecteerd, en het kan veel subtieler en zelfs snodeder zijn. (De eerste aanvallen kunnen pogingen zijn om informatie over tabellen en kolommen op te halen, gevolgd door pogingen om gegevens op te halen (e-mailadressen, rekeningnummers, enz.)

Een manier om dit beveiligingslek aan te pakken is om de inhoud van @KeyValue te valideren, zeg dat het alleen alfabetische en numerieke tekens mag bevatten (controleer bijvoorbeeld op tekens die niet in die reeksen vallen met behulp van LIKE '%[^A-Za-z0-9]%' . Als een ongeldig teken wordt gevonden, verwerp dan de waarde en sluit af zonder enige SQL uit te voeren.



  1. Prestatieverbetering van PostgreSQL 9.6 opgeslagen procedure

  2. Is er een betere manier om machtigingen toe te wijzen aan tijdelijke tabellen in MySQL?

  3. Manieren om SQL Server Database te migreren naar Azure SQL Database

  4. Aqua Data Studio