Reputation: 29
I want to build a SQL command dynamically by checking if a parameter is null. If it is not null, it will be added to the command string. The stored procedure can be compiled, but at running time I get an invalid syntax error. Here is the code I've written so far:
CREATE PROCEDURE searchEvents @name VARCHAR(50), @location VARCHAR(20), @postcode CHAR(4), @address VARCHAR(40), @startDate DATETIME, @endDate DATETIME
AS
DECLARE
@sqlCommand NVARCHAR(MAX) = 'SELECT Event.Name, Description, Location.Name AS Location, Postcode, Address, StartDate, EndDate, Website FROM Event JOIN Location ON Event.LocationID = Location.LocationID',
@parameters NVARCHAR(MAX),
@whereIncluded BIT = 0
BEGIN
IF @name IS NOT NULL
BEGIN
IF @whereIncluded = 0
BEGIN
SET @sqlCommand = @sqlCommand + ' WHERE '
SET @whereIncluded = 1
END
ELSE
SET @sqlCommand = @sqlCommand + ' AND '
SET @sqlCommand = @sqlCommand + 'Event.Name LIKE ' + '%' + @name + '%'
END
-- It's the same if clause for all parameters like above
SET @parameters = N'@p_name VARCHAR(50), @p_location VARCHAR(20), @p_postcode CHAR(4), @p_address VARCHAR(40), @p_startDate DATETIME, @p_endDate DATETIME'
EXEC sp_executesql
@sqlCommand,
@parameters,
@p_name = @name,
@p_location = @location,
@p_postcode = @postcode,
@p_address = @address,
@p_startDate = @startDate,
@p_endDate = @endDate
END
The query I execute:
EXEC searchEvents 'Wine fair', NULL, NULL, NULL, NULL, NULL
The error I get:
Incorrect syntax near "Wine fair".
Upvotes: 1
Views: 180
Reputation: 46231
Add a PRINT
statement for debugging and the reason for the error will be clear:
WHERE Event.Name LIKE %Wine fair%
As you can see, the single-quotes around the intended literal are missing.
Note that this code is vulnerable to SQL injection. If you only add the missing quotes and use string concatenation, malicious SQL can be injected. Instead, specify the parameter value directly in the generated SQL statement rather than a string literal. The example below also escapes LIKE
wildcards so that the desired results are returned even if the user-supplied value contains them.
SET @name = REPLACE(@name,'%', '[%]'); --escape % wildcard
SET @name = REPLACE(@name,'_', '[_]'); --escape _ wildcard
SET @name = REPLACE(@name,'[', '[[]'); --escape [ wildcard
SET @name = '%' + @name + '%' --add desired wildcards
SET @sqlCommand = @sqlCommand + 'Event.Name LIKE @name'; --use parameter directly in SQL statement
Also make sure the application runs under a minimally-privileged account. For maximum security, use sign the stored procedure with a certificate associated with a user with the needed SELECT
permissions. That way, the app only needs execute permissions on the proc.
Upvotes: 3
Reputation: 2191
You missed quotes
SET @sqlCommand = @sqlCommand + 'Event.Name LIKE ' + '''%' + @name + '%'''
UPD: To avoid SQL injection:
SET @sqlCommand = @sqlCommand + 'Event.Name LIKE ''%'' + @p_name + ''%'''
Upvotes: 1