代码之家  ›  专栏  ›  技术社区  ›  Ricardo Alves

我可以将if条件与存储过程中的fetch结合起来吗?

  •  1
  • Ricardo Alves  · 技术社区  · 7 年前

    我正在开发一个应该接受一些参数的存储过程。其中一个参数告诉我应该记录多少,但是如果它的值小于或等于0,那么它应该获取所有的行。我开发了以下我不喜欢的解决方案:

    IF (@take > 0) BEGIN
        SELECT
              *
        FROM Properties
            -- Some conditions and joins are here using other parameters
            -- A big Order by with cases is placed here
        OFFSET @skip ROWS
        FETCH NEXT @take ROWS ONLY;
    END
    ELSE BEGIN
                SELECT
              *
        FROM Properties
            -- Some conditions and joins are here using other parameters
            -- A big Order by with cases is placed here
        OFFSET @skip ROWS;
    END;
    

    上述条件的问题是,除了if条件中的最后一行之外,我必须确保SQL语句是相等的。我还尝试过的方法之一是构造一个查询字符串并使用exec执行它,但是其中一个变量将直接来自用户,因此我容易受到SQL注入的攻击。

    我还必须改进上述代码,以允许SP接收一个参数,告诉它是否应按某个字段“分组”,这将使我在每个条件中添加另一个分支(因此,上述解决方案的可伸缩性不是很强)。有更好的方法吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Damien_The_Unbeliever    7 年前

    您可以使用 CASE 表达而不是使用 @take 直接变量:

    SELECT
          *
    FROM Properties
        -- Some conditions and joins are here using other parameters
        -- A big Order by with cases is placed here
    OFFSET @skip ROWS
    FETCH NEXT CASE WHEN @take > 0 THEN @take ELSE 1000001 END ROWS ONLY;
    

    当然,这需要你为 ELSE 这比您希望查询返回的任何合理结果集都要大。我通常选择一个整数并添加一个,目的是显示最多“整数”结果,如果得到额外的结果,我至少可以包含一个指示器,表明查询返回的结果比这个还要多。

    这是基于这样一个假设:用户正在控制过滤,而您希望/能够说“您知道什么,结果太多了”。如果您真的想完成所有这些任务,但我现在不打算向您展示所有这些任务,请使用分页功能”。


    我还必须改进上述代码,以允许SP接收一个参数,告诉它是否应按某个字段“分组”。

    这是一个更棘手的建议。带有 GROUP BY 子句必须包含 SELECT 包含列的子句 分组依据 条款或 聚合表达式 . (如果没有聚合,分组的意义是什么?)。这与非分组查询有本质的不同,因此您不能使用简单的开关/标志在它们之间进行真正的切换。

    此时,查询不太可能有太多的相似性(除了 FROM 您可能希望移到视图或表值函数中以便重用的子句),或者需要切换到动态SQL。