I wrote the following stored procedure for querying the database. Can someone tell me if this dynamic query stored procedure is vulnerable to a SQL injection attack?
If it is, how to modify the following code to prevent SQL injection attacks?
The second question is OPTION (RECOMPILE) at the end of the WHERE cause, is it necessary with every execution?
CREATE PROCEDURE DataMapMainQuery
(@DataMapID VARCHAR(MAX),
@DataMapIDName VARCHAR(MAX),
@StartIndex INT,
@MaximumRows INT,
@sortExpression VARCHAR(MAX))
AS
BEGIN
DECLARE @FilteredTotalRows AS INT
DECLARE @SqlString NVARCHAR(MAX)
DECLARE @WhereString1 NVARCHAR(MAX)
DECLARE @WhereString2 NVARCHAR(MAX)
IF (@DataMapID IS NULL)
SET @WhereString1 = ' AND (DataMapID LIKE ' + '''%%''' + ' OR NULL IS NULL)'
ELSE
SET @WhereString1 = ' AND (DataMapID LIKE ' + '''%' + @DataMapID + '%''' + ' OR ''' + @DataMapID + ''' IS NULL)'
IF (@DataMapIDName IS NULL)
SET @WhereString2 = ' AND (DataMapIDName LIKE ' + '''%%''' + ' OR NULL IS NULL)'
ELSE
SET @WhereString2 = ' AND (DataMapIDName LIKE ' + '''%' + @DataMapIDName + '%''' + ' OR ''' + @DataMapIDName + ''' IS NULL)'
IF (@sortExpression IS NULL)
SET @sortExpression = 'DataMapID'
SELECT
@FilteredTotalRows = COUNT(*)
FROM
DataMapMain
WHERE
1 = 1
AND (DataMapID LIKE '%' + @DataMapID + '%' OR @DataMapID IS NULL)
AND (DataMapIDName LIKE '%' + @DataMapIDName + '%' OR @DataMapIDName IS NULL)
IF (@FilteredTotalRows < @StartIndex + 1)
BEGIN
SET @SqlString = '
SELECT
DataMapID, DataMapIDName,
DataMapGroup, DataMapGroupRemark,
CONVERT(BIGINT, TimeStamp) AS TimeStamp
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY ' + @sortExpression + ') AS RowNumber,
DataMapID, DataMapIDName,
DataMapGroup, DataMapGroupRemark,
TimeStamp
FROM
DataMapMain
WHERE
1 = 1'
+ @WhereString1
+ @WhereString2
+ ') DataMapMain
WHERE
RowNumber >= 1
AND RowNumber < (1 + ' + CONVERT(NVARCHAR(10), @MaximumRows) + ')
OPTION (RECOMPILE)'
END
ELSE
BEGIN
SET @SqlString = '
SELECT
DataMapID
,DataMapIDName
,DataMapGroup
,DataMapGroupRemark
,CONVERT(bigint, TimeStamp) as TimeStamp
FROM
(
Select ROW_NUMBER() over (order by ' + @sortExpression + ') as RowNumber
,DataMapID
,DataMapIDName
,DataMapGroup
,DataMapGroupRemark
,TimeStamp
From DataMapMain
WHERE
1 = 1'
+ @WhereString1
+ @WhereString2
+ ') DataMapMain
WHERE
RowNumber >= (' + CONVERT(nvarchar(10),@StartIndex) + ' + 1) and RowNumber < (' + CONVERT(nvarchar(10),@StartIndex) + ' + 1 + ' + CONVERT(nvarchar(10),@MaximumRows) + ' )
OPTION (RECOMPILE)'
END
PRINT @SqlString
PRINT @FilteredTotalRows
EXEC sp_executesql @SqlString
END