【问题标题】:Nested if statements in SQL Server stored procedure SELECT statementSQL Server 存储过程 SELECT 语句中的嵌套 if 语句
【发布时间】:2010-12-24 05:26:36
【问题描述】:

我是新来的,对存储过程比较陌生,所以请多多包涵!我在这里检查了相关问题,但找不到在这种情况下有效的任何东西。

我正在尝试构建一个存储过程 (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 语句的一般概念。

【问题讨论】:

标签: sql-server-2005 stored-procedures nested


【解决方案1】:

试试这个方法:

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         

来源文章:
http://blog.sqlauthority.com/2007/07/17/sql-server-case-statement-in-order-by-clause-order-by-using-variable/

【讨论】:

  • 谢谢所有回复的人,我想我的存储过程的这一部分现在已经排序了。非常感谢。
【解决方案2】:

根据字段的数据类型,如果不允许使用空值,您可能有的另一个选择是执行类似的操作。

选择 * FROM database.dbo.table T WHERE T.deleted = 'n' AND fieldf1 = COALESCE(@searchf1, fieldf1) AND fieldr1 = COALESCE(@searchr1, fieldr1) - 等等 ORDER BY fieldf1

这种方式你不使用动态 SQL 并且它是相当可读的,当你想要省略数据时,只需让变量为空。

注意:正如我所提到的,如果任何 COALESCE 列包含空值,则此路由将不起作用。

【讨论】:

  • 谢谢米切尔。不幸的是,我正在搜索包含空值的列。无论如何,请欣赏输入,我将保存它以供将来参考,其中数据库不包含遗留的空值。
【解决方案3】:

为此,考虑到您定义的输入参数,我会尝试使用更正式的动态 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 注入攻击,然而,对于一些动态搜索类型的操作,它是最优雅的途径之一。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    • 2011-03-16
    • 2019-02-27
    • 2023-04-03
    相关资源
    最近更新 更多