The following stored procedure works correctly execpt when I pass in the @NameSubstring parameter. I know I am not dynamically building the like clause properly. How can I build the like clause when this parameter also needs to be passed as a parameter in the EXEC sp_executesql call near the bottom of the procedure?
ALTER PROCEDURE [dbo].[spGetAutoCompleteList]
(
@AutoCompleteID int,
@StatusFlag int,
@NameSubstring varchar(100),
@CompanyID int,
@ReturnMappings bit,
@ReturnData bit
)
AS
DECLARE @ErrorCode int,
@GetMappings nvarchar(500),
@Debug bit,
@Select AS NVARCHAR(4000),
@From AS NVARCHAR(4000),
@Where AS NVARCHAR(4000),
@Sql AS NVARCHAR(4000),
@Parms AS NVARCHAR(4000)
SET @ErrorCode = 0
SET @Debug = 1
BEGIN TRAN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF @AutoCompleteID IS NOT NULL OR @StatusFlag IS NOT NULL OR @NameSubstring IS NOT NULL
BEGIN
SET @Select = '
SELECT ac.AutoCompleteID,
ac.AutoCompleteName,
ac.CompanyID,
ac.StatusFlag,
ac.OwnerOperID,
ac.CreateDT,
ac.CreateOperID,
ac.UpdateDT,
ac.UpdateOperID,
ac.SubmitOperID,
ac.SubmitDT,
ac.ReviewComments'
SET @GetMappings = '
Select ac.AutoCompleteID'
IF @ReturnData = 1
BEGIN
SET @Select = @Select + '
, ac.AutoCompleteData'
END
SET @From = '
FROM tbAutoComplete ac'
SET @Where = '
WHERE 1=1'
IF @AutoCompleteID IS NOT NULL
BEGIN
SET @Where = @Where + '
AND ac.AutoCompleteID = CAST(@AutoCompleteID AS nvarchar)'
END
IF @StatusFlag IS NOT NULL
BEGIN
SET @Where = @Where + '
AND ac.StatusFlag = CAST(@StatusFlag AS nvarchar)'
END
IF @NameSubstring IS NOT NULL
BEGIN
SET @Where = @Where + '
AND ac.AutoCompleteName like @NameSubstring' + '%'
END
SET @Where = @Where + '
AND ac.CompanyID = + CAST(@CompanyID AS nvarchar)'
SET @Sql = @Select + @From + @Where
SET @Parms = '
@AutoCompleteID int,
@StatusFlag int,
@NameSubstring varchar(100),
@CompanyID int'
EXEC sp_executesql @Sql,
@Parms,
@AutoCompleteID,
@StatusFlag,
@NameSubstring,
@CompanyID
IF @ReturnMappings = 1
BEGIN
SET @GetMappings = 'Select * FROM tbAutoCompleteMap acm WHERE acm.AutoCompleteID IN(' + @GetMappings + @From + @Where + ')'
--EXEC sp_executesql @GetMappings
END
IF @Debug = 1
BEGIN
PRINT @GetMappings
PRINT @Sql
END
END
SELECT @ErrorCode = @ErrorCode + @@ERROR
IF @ErrorCode <> 0
BEGIN
SELECT '<FaultClass>1</FaultClass><FaultCode>1</FaultCode>'
+ '<FaultDesc>Internal Database Error.</FaultDesc>'
+ '<FaultDebugInfo>(spGetAutoCompleteList): There was an error while trying to SELECT from tbAutoComplete.</FaultDebugInfo>'
ROLLBACK TRAN
RETURN
END
COMMIT TRAN
So, you are asking how to specify parameters when you use dynamic queries and
sp_executesql
?It can be done, like this:
You can read more about it here: http://support.microsoft.com/kb/262499
SET @Where = @Where + 'AND ac.AutoCompleteName like ''%' + @NameSubstring + '%'''
@NameString needs to be outside of the quotes. To get @NameString% enclosed in quotes, you use two single quotes to escape the quote character as a literal.
Perhaps this wouldn't be an issue if you weren't using dynamic SQL. It looks to me like a vanilla query would work just as well and be much more straightforward to read and debug. Consider the following:
This is much simpler, clearer etc. Good luck!
To avoid SQL injection, do not use concatenation when adding the parameter to your SQL statement. I strongly recommend that you use this format:
By using
char(37)
instead of'%'
you avoid having to escape the apostrophes around the string literalIf you wanted to put a wildcard at either side, then you would use
-----------------------------------------------------------------------------
In case someone believes I am wrong, here's proof that concatenation is a risk.
Run it the first time and you will get a resultset with 3 records, and another with all 6 records.
Now swap the declaration of
@NameSubstring
to the alternative, and re-run. All data in the table has been deleted.If on the other hand you write your code like:
Then you still get the 3 records returned the first time, but you don't lose your data when you change the declaration.