我写了这个程序并定义了两个字符串作为它的参数:
CREATE PROCEDURE [dbo].[spo_SelectTable1sDynamic]
@WhereCondition nvarchar(500),
@OrderByExpression nvarchar(250) = NULL
AS
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
DECLARE @SQL nvarchar(3250)
SET @SQL = 'SELECT
[col1], [col2], [col3], [col4]
FROM
[dbo].[Table1]
WHERE
' + @WhereCondition
IF @OrderByExpression IS NOT NULL AND LEN(@OrderByExpression) > 0
BEGIN
SET @SQL = @SQL + 'ORDER BY ' + @OrderByExpression
END
EXEC sp_executesql @SQL
我应该为@whereconditio
和@OrderByExpression
参数传递两个字符串。
如何执行此存储过程?我使用此代码但收到错误:
EXECUTE spo_SelectTable1sDynamic N'col1='book'' , N'col1 '
答案 0 :(得分:3)
首先,您的代码非常容易受到SQL Injection攻击。
第二个SELECT * FROM tbl WHERE @condition是诅咒:
如果您正在考虑编写程序
CREATE PROCEDURE search_sp @condition varchar(8000) AS SELECT * FROM tbl WHERE @condition
忘了它。如果你这样做,你还没有完成 过渡到使用存储过程,你仍在组装你的 客户端中的SQL代码。
可能的解决方案是使用动态搜索条件并完全避免使用动态SQL:
CREATE PROCEDURE [dbo].[spo_SelectTable1sDynamic]
@col1 NVARCHAR(1000), -- depending on business cases
@col2 INT ...,
@sortColumn SYSNAME
AS
BEGIN
SELECT ....
FROM table ...
WHERE (col1 = @col1 OR @col1 IS NULL)
AND (col2 = @col2 OR @col2 IS NULL) ...
ORDER BY
CASE @sortColumn
WHEN 'col1' THEN col1
WHEN 'col2' THEN col2
...
END
END
用户可以将其称为:
EXEC [dbo].[spo_SelectTable1sDynamic] @col1 = 'aaa'
EXEC [dbo].[spo_SelectTable1sDynamic] @col2 = 10
EXEC [dbo].[spo_SelectTable1sDynamic] @col1 = 'bbb', @col2 = 16
-- or even
EXEC [dbo].[spo_SelectTable1sDynamic
-- to get all possible rows without any filter