Uważam, że istnieją trzy różne przypadki, o które musisz się martwić:
- strings (wszystko, co wymaga cudzysłowów):
'''' + replace(@string, '''', '''''') + ''''
- nazwy (wszystko, gdzie cudzysłowy nie są dozwolone):
quotename(@string)
- rzeczy, których nie można zacytować:wymaga to umieszczenia na białej liście
Uwaga :Wszystko w zmiennej łańcuchowej (char
, varchar
, nchar
, nvarchar
itp.), które pochodzą ze źródeł kontrolowanych przez użytkownika, muszą korzystać z jednej z powyższych metod. Oznacza to, że nawet rzeczy, które mają być liczbami, są cytowane, jeśli są przechowywane w zmiennych łańcuchowych.
Więcej informacji znajdziesz w Microsoft Magazine (Przestarzały link:2016-10-19) .
Oto przykład wykorzystujący wszystkie trzy metody:
EXEC 'SELECT * FROM Employee WHERE Salary > ''' +
REPLACE(@salary, '''', '''''') + -- replacing quotes even for numeric data
''' ORDER BY ' + QUOTENAME(@sort_col) + ' ' + -- quoting a name
CASE @sort_dir WHEN 'DESC' THEN 'DESC' END -- whitelisting
Zwróć też uwagę, że wykonując wszystkie operacje na ciągach znaków w pliku EXEC
oświadczenie, że nie ma problemu z obcięciem. Jeśli przypiszesz wyniki pośrednie do zmiennych, musisz upewnij się, że zmienne są wystarczająco duże, aby pomieścić wyniki. Jeśli zrobisz SET @result = QUOTENAME(@name)
powinieneś zdefiniować @result
mieć co najmniej 258 (2 * 128 + 2) znaków. Jeśli wykonasz SET @result = REPLACE(@str, '''', '''''')
powinieneś zdefiniować @result
być dwukrotnie większy od @str
(przyjmij każdy znak w @str
może być cytat). I oczywiście zmienna łańcuchowa zawierająca końcową instrukcję SQL musi być wystarczająco duża, aby pomieścić cały statyczny kod SQL oraz wszystkie zmienne wynikowe.