我是新来的,对存储过程比较新,所以请耐心等待!我在这里检查了相关问题,但在这个例子中找不到任何有用的东西。
我正在尝试构建一个存储过程(MS SQL Server 2005),该过程接受大量传入的值,实际上动态构建SQL,就像使用内联SQL一样。
这就是我失败的地方。
我们(为了清晰起见而略微简化):
@searchf1 varchar(100), -- search filter 1
@searchr1 varchar(100), -- search result 1
@searchf2 varchar(100), -- search filter 2
@searchr2 varchar(100), -- search result 2
@direction char(1), -- direction to order results in
AS
set nocount on
set dateformat dmy
SELECT *
FROM database.dbo.table T
WHERE T.deleted = 'n'
ORDER BY CASE @direction
WHEN 'A' THEN T.id
WHEN 'D' THEN T.id DESC
END
END
set nocount off
我也尝试过ORDER BY的行:
IF @direction = 'N' THEN
ORDER BY
T.id
ELSE
ORDER BY
T.id DESC
这两种方法都给我一个错误:
“关键字'DESC'附近的语法不正确。” (引用最终ORDER BY之后的行ID DESC
作为此存储过程的一部分,我还想尝试输入匹配的值对,这些值引用要查找的字段和与之匹配的字段,这些值可以存在或者为''。为此,我需要在SELECT部分代码中添加类似于:
的代码WHERE
deleted = 'n'
IF @searchf1 <> '' THEN
AND fieldf1 = @searchf1 AND fieldr1 = @searchr1
然而,这会产生如下错误:
关键字“IF”附近的语法不正确。
我知道这种类型的动态SQL并不是最优雅的。而且我知道我可以用glocal IF ELSE语句做到这一点,但是如果我这样做,那么SP会长达数千行;最多可以有15对这些搜索字段,以及指示该方向的方向和字段。
(此SP的当前版本使用传入的ID列表来返回由某些内联动态SQL生成的内容,通过执行此操作,我尝试将其减少为一次命中以生成记录集)
任何帮助非常感谢。为了清楚起见,我已经大大简化了上面例子中的代码,因为它是我正在询问的带有SELECT和ORDER BY的嵌套IF语句的一般概念。
答案 0 :(得分:2)
为此我会尝试使用更正式的动态SQL解决方案,如下所示,给定您定义的输入参数
DECLARE @SQL VARCHAR(MAX)
SET @SQL = '
SELECT
FROM
database.dbo.table T
WHERE
T.deleted = ''n'' '
--Do your conditional stuff here
IF @searchf1 <> '' THEN
SET @SQL = @SQL + ' AND fieldf1 = ' + @searchf1 + ' AND fieldr1 = ' + @searchr1 + ''' '
--Finish the query
SET @SQL = @SQL + ' ORDER BY xxx'
EXEC(@SQL)
免责声明: 动态SQL的使用不应该被轻视,并且应该在所有情况下都要正确考虑,以确保您不会对但是,SQL注入攻击对于某些动态搜索类型的操作来说,它是最优雅的路径之一。
答案 1 :(得分:2)
以这种方式尝试:
SELECT * FROM database.dbo.table T WHERE T.deleted = 'n'
ORDER BY
CASE WHEN @direction='A' THEN T.id END ASC,
CASE WHEN @direction='D' THEN T.id END DESC
答案 2 :(得分:0)
根据字段的数据类型,如果不允许空值,您可能拥有的另一个选项是执行类似的操作。
SELECT * FROM database.dbo.table T. WHERE T.deleted ='n' AND fieldf1 = COALESCE(@ searchf1,fieldf1) AND fieldr1 = COALESCE(@ searchr1,fieldr1) - 等等 ORDER BY fieldf1
通过这种方式,您不使用动态SQL并且它具有可读性,当您想要省略数据时,只需将变量设为null。
注意: 正如我所提到的,如果任何COALESCE列包含空值,则此路由将不起作用。