Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come concatenare le variabili in stringhe SQL

Puoi farlo (se ho capito cosa stai cercando di fare) usando SQL dinamico.

Il trucco è che devi creare una stringa contenente l'istruzione SQL. Questo perché il nome della tabella deve essere specificato nel testo SQL effettivo, quando si esegue l'istruzione. I riferimenti alle tabelle e alle colonne non possono essere forniti come parametri, devono apparire nel testo SQL.

Quindi puoi usare qualcosa come questo approccio:

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

EXEC (@stmt)

Innanzitutto, creiamo un'istruzione SQL come stringa. Dato un @KeyValue di 'Foo', ciò creerebbe una stringa contenente:

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

A questo punto, è solo una stringa. Ma possiamo eseguire il contenuto della stringa, come un'istruzione SQL dinamica, usando EXECUTE (o EXEC in breve).

La vecchia scuola sp_executesql procedura è un'alternativa a EXEC, un altro modo per eseguire SQL dinamico, che consente anche di passare parametri, invece di specificare tutti i valori come letterali nel testo dell'istruzione.

SEGUITO

EBarr sottolinea (correttamente e soprattutto) che questo approccio è suscettibile di SQL Injection.

Considera cosa accadrebbe se @KeyValue conteneva la stringa:

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

La stringa che produrremmo come istruzione SQL sarebbe:

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

Quando ESEGUIAMO quella stringa come un'istruzione SQL:

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

E non è solo un DROP TABLE che potrebbe essere iniettato. Qualsiasi SQL potrebbe essere iniettato e potrebbe essere molto più sottile e persino più nefasto. (I primi attacchi possono essere tentativi di recuperare informazioni su tabelle e colonne, seguiti da tentativi di recuperare dati (indirizzi e-mail, numeri di conto, ecc.)

Un modo per affrontare questa vulnerabilità è convalidare il contenuto di @KeyValue, ad esempio dovrebbe contenere solo caratteri alfabetici e numerici (ad es. verificare la presenza di caratteri non in quegli intervalli utilizzando LIKE '%[^A-Za-z0-9]%' . Se viene trovato un carattere non valido, rifiuta il valore ed esci senza eseguire SQL.