代码之家  ›  专栏  ›  技术社区  ›  SharePoint Newbie

如何将空作为参数限制到存储过程SQL Server?

  •  33
  • SharePoint Newbie  · 技术社区  · 16 年前

    是否可以将存储过程创建为

    CREATE PROCEDURE Dummy 
        @ID INT NOT NULL
    AS
    BEGIN
    END
    

    为什么不可能这样做?

    4 回复  |  直到 6 年前
        1
  •  -5
  •   dkretz    9 年前

    参数验证当前不是SQL Server中过程逻辑的一个功能,而非空仅是一种可能的数据验证类型。表中的char数据类型具有长度规范。是否也应该实施?您如何处理异常?对于表模式中的异常处理,有一种广泛的、高度开发的、某种程度上基于标准的方法;但对于过程逻辑则没有,这可能是因为过程逻辑是在关系系统之外定义的。另一方面,存储过程已经有了一种引发错误事件的现有机制,这种机制与许多API和语言绑定在一起。对于参数上的声明性数据类型约束没有这样的支持。添加它的含义是广泛的;特别是因为它得到了很好的支持和扩展,只需添加代码:

    IF ISNULL(@param) THEN
        raise error ....
    END IF
    

    在存储过程的上下文中,空的概念甚至没有很好的定义,特别是与表或SQL表达式的上下文相比。这不是微软的定义。SQL标准组花了很多年的时间生成了大量的文献,建立了空的行为和该行为定义的界限。存储过程不是其中之一。

    存储过程被设计为尽可能轻,以使数据库性能尽可能高效。参数的数据类型不用于验证,而是使编译器能够为查询优化器提供更好的信息,以便编译尽可能好的查询计划。参数上的非空约束通过使编译器更复杂以验证参数的新目的,朝着另一条完整的路径前进。因此效率更低,重量更重。

    有一个原因就是存储过程没有被写为C函数。

        2
  •  42
  •   Unsliced    16 年前

    您可以在存储过程中检查它的空性,并且 RAISERROR 将状态报告回呼叫位置。

    CREATE   proc dbo.CheckForNull @i int 
    as
    begin
      if @i is null 
        raiserror('The value for @i should not be null', 15, 1) -- with log 
    
    end
    GO
    

    然后呼叫:

    exec dbo.CheckForNull @i = 1 
    

    exec dbo.CheckForNull @i = null 
    
        3
  •  13
  •   Patrick Fromberg    10 年前

    您的代码是正确的、明智的,甚至是良好的实践。你只需要等待 SQL Server 2014 它支持这种语法。

    毕竟,为什么在运行时可以在编译时捕获?

    也见 this msdn document 寻找 Natively Compiled 在那里。

    正如dkrez所说,nullabiliy不被视为数据类型定义的一部分。我仍然想知道为什么不呢。

        4
  •  0
  •   BigBother    6 年前

    哦,看来我不能编辑@unsliced post,因为“这个编辑偏离了邮件的原始意图。即使编辑必须做出巨大的改变,也应该努力保持帖子所有者的目标。

    所以(@crokusek和所有感兴趣的人)这是我的解决方案:

    您可以在存储过程中检查它的空性,并且 RAISERROR 将状态报告回呼叫位置。

    CREATE proc dbo.CheckForNull 
      @name sysname = 'parameter',
      @value sql_variant
    as
    begin
      if @value is null
        raiserror('The value for %s should not be null', 16, 1, @name) -- with log
    end
    GO
    

    然后呼叫:

    exec dbo.CheckForNull @name 'whateverParamName', @value = 1
    

    exec dbo.CheckForNull @value = null