Przepraszamy za długie pytanie, ale zawiera ono cały SQL, którego użyłem do przetestowania scenariusza, aby mieć nadzieję, co do tego, co robię.Serwer SQL - dynamiczna tablica PIVOT - SQL Injection
Jestem zbudować jakiś dynamiczny SQL w celu uzyskania tabeli przestawnej w programie SQL Server 2005.
Poniżej jest kod, aby to zrobić. Z różnymi zaznaczeniami pokazującymi nieprzetworzone dane wartości przy użyciu GROUP BY i wartości w PIVOT, jak chcę.
BEGIN TRAN
--Create the table
CREATE TABLE #PivotTest
(
ColumnA nvarchar(500),
ColumnB nvarchar(500),
ColumnC int
)
--Populate the data
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'X', 1)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'Y', 2)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'Z', 3)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'X', 4)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'Y', 5)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('B', 'Z', 6)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('B', 'X', 7)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('B', 'Y', 8)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('B', 'Z', 9)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('C', 'X', 10)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('C', 'Y', 11)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('C', 'Z', 12)
--The data
SELECT * FROM #PivotTest
--Group BY
SELECT
ColumnA,
ColumnB,
SUM(ColumnC)
FROM
#PivotTest
GROUP BY
ColumnA,
ColumnB
--Manual PIVOT
SELECT
*
FROM
(
SELECT
ColumnA,
ColumnB,
ColumnC
FROM
#PivotTest
) DATA
PIVOT
(
SUM(DATA.ColumnC)
FOR
ColumnB
IN
(
[X],[Y],[Z]
)
) PVT
--Dynamic PIVOT
DECLARE @columns nvarchar(max)
SELECT
@columns =
STUFF
(
(
SELECT DISTINCT
', [' + ColumnB + ']'
FROM
#PivotTest
FOR XML PATH('')
), 1, 1, ''
)
EXEC
('
SELECT
*
FROM
(
SELECT
ColumnA,
ColumnB,
ColumnC
FROM
#PivotTest
) DATA
PIVOT
(
SUM(DATA.ColumnC)
FOR
ColumnB
IN
(
' + @columns + '
)
) PVT
')
--The data again
SELECT * FROM #PivotTest
ROLLBACK
Zawsze, gdy produkuję dynamiczny SQL, zawsze mam świadomość ataków SQL Injection. Dlatego dodałem następujący wiersz do innych instrukcji INSERT.
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'FOO])) PVT; DROP TABLE #PivotTest;SELECT ((GETDATE()--', 1)
Kiedy teraz uruchomić SQL, niskie i oto część EXEC spada zatem #PivotTest stół czyniąc ostatni SELECT niepowodzeniem.
Moje pytanie brzmi, czy ktoś wie o sposobie wykonywania dynamicznego PIVOT bez ryzyka ataków SQL Injection?
1) Moja próbka testowa jest prosta. Rzeczywiste kolumny to nvarchar (max). Nie mamy obecnie danych o takiej wielkości, a dane, które byłyby użyte w PIVOT rzadko sięgałyby nawet 100, więc mogę wykonać wymuszone obcięcie w tym przypadku! Świetny pomysł. 2) Myślałem o "[" i "]". Mam ochotę usunąć wszystkie nawiasy kwadratowe z danych i po prostu mam to jako ograniczenie tej funkcjonalności. 3) Jedynymi osobami, które mogą dodać te dane, są tzw. "Superużytkownicy", ale to nie wystarczy, aby zapewnić mi spokój. –
QUOTENAME! Pierwszy raz widziałem to! Idealny! To całkowicie rozwiązuje problem. Dodałem QUOTES ręcznie.Jeśli usuniemy to i zrobię to za pomocą QUOTENAME, to wyłączy to SQL w tym polu! DZIĘKUJĘ CI! –