Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server 2005:;“保护”;MS Access使用的FMTONLY模式的存储过程_Sql Server_Ms Access_Stored Procedures_Coding Style - Fatal编程技术网

Sql server SQL Server 2005:;“保护”;MS Access使用的FMTONLY模式的存储过程

Sql server SQL Server 2005:;“保护”;MS Access使用的FMTONLY模式的存储过程,sql-server,ms-access,stored-procedures,coding-style,Sql Server,Ms Access,Stored Procedures,Coding Style,我们的一些存储过程包含条件逻辑,如下所示: Create Procedure dbo.DoSomething(Some Parameters) As ... If (Some Condition) Begin Set @SomeVariable = SomeValue End ... Select ... Create Procedure dbo.DoSomething(Some Parameters) A

我们的一些存储过程包含条件逻辑,如下所示:

Create Procedure dbo.DoSomething(Some Parameters)
As
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    Select ...
Create Procedure dbo.DoSomething(Some Parameters)
As
    ...

    -- HACK: Protection from unexpected FMTONLY mode
    Declare @wasFmtonlyOn As Bit; If (0 = 1) Set @wasFmtonlyOn = 1; SET FMTONLY OFF
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    -- /HACK: Protection from unexpected FMTONLY mode
    If (@wasFmtonlyOn = 1) SET FMTONLY ON

    ...
    Select ...
Create Procedure dbo.DoSomething(Some Parameters)
As
    ...

    declare @wasFmtonlyOn as bit; set @wasFmtonlyOn = dbo.SetFmtonly(0)
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    dbo.SetFmtonly(@wasFmtonlyOn)

    ...
    Select ...
当此类存储过程用作MS Access窗体的记录源,并且用户尝试使用窗体的内置排序/筛选功能时,MS Access将尝试以FMTONLY模式执行存储过程(显然,查找存储过程提供的行集的元数据)

正如大多数人所知(现在包括我们自己:-),当FMTONLY设置为ON时,SQLServer会忽略条件语句。在下面所示的示例中,执行
Set@SomeVariable=SomeValue
语句,而不管
某些条件是否为真,这显然给我们带来了一些麻烦

-- EXAMPLE
-- -------
Create Procedure dbo.DoSomething(..., @vcSomeDate as VarChar(50), ...)
As
   ...
   Declare @dtSomeDate As Datetime
   If (IsDate(@vcSomeDateOrAgeInDays)) Begin
       -- The next statement fails miserably when FMTONLY=ON
       Set @dtSomeDate = @vcSomeDateOrAgeInDays
   End Else Begin
       ...
   End
   ...
为了避免这个问题,我们像这样“包装”条件逻辑(或受FMTONLY影响的任何其他代码片段):

Create Procedure dbo.DoSomething(Some Parameters)
As
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    Select ...
Create Procedure dbo.DoSomething(Some Parameters)
As
    ...

    -- HACK: Protection from unexpected FMTONLY mode
    Declare @wasFmtonlyOn As Bit; If (0 = 1) Set @wasFmtonlyOn = 1; SET FMTONLY OFF
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    -- /HACK: Protection from unexpected FMTONLY mode
    If (@wasFmtonlyOn = 1) SET FMTONLY ON

    ...
    Select ...
Create Procedure dbo.DoSomething(Some Parameters)
As
    ...

    declare @wasFmtonlyOn as bit; set @wasFmtonlyOn = dbo.SetFmtonly(0)
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    dbo.SetFmtonly(@wasFmtonlyOn)

    ...
    Select ...
(这种丑陋的“保护代码”单行格式是有意为之的:我们认为解决一些奇怪问题所需的黑客不值得进行适当的格式设置;恰恰相反,我们认为他们应该尽可能少地放入代码行中。:-)

无论如何,这个“保护”工作得很好,但它有点太冗长,没有我们想要的那么多封装。例如,我们肯定更愿意隐藏黑客的实际逻辑-例如,在标量UDF后面,如下所示:

Create Procedure dbo.DoSomething(Some Parameters)
As
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    Select ...
Create Procedure dbo.DoSomething(Some Parameters)
As
    ...

    -- HACK: Protection from unexpected FMTONLY mode
    Declare @wasFmtonlyOn As Bit; If (0 = 1) Set @wasFmtonlyOn = 1; SET FMTONLY OFF
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    -- /HACK: Protection from unexpected FMTONLY mode
    If (@wasFmtonlyOn = 1) SET FMTONLY ON

    ...
    Select ...
Create Procedure dbo.DoSomething(Some Parameters)
As
    ...

    declare @wasFmtonlyOn as bit; set @wasFmtonlyOn = dbo.SetFmtonly(0)
    ...
    If (Some Condition) Begin
        Set @SomeVariable = SomeValue                
    End
    ...
    dbo.SetFmtonly(@wasFmtonlyOn)

    ...
    Select ...
不幸的是,这似乎不起作用——标量UDF也不起作用,另一个存储过程也不起作用。看起来fmtony可以防止从任何地方返回任何数据。那么,主要问题来了:

如果您还必须处理这个问题(SQLServer在FMTONLY模式下忽略条件),您是否能够想出比上面描述的更好的“保护习惯用法”

顺便说一句,我仍然不明白一件事:这个问题是SQLServer2005中的一个bug还是一个特性?如果这是一个功能,那么什么可能是它的一个很好的理由呢

谢谢大家!

这个怎么样

If (Some Condition) Begin
    Set @SomeVariable = SomeValue
ELSE
    Set @SomeVariable = @SomeVariable --or dummy/default value?
End
您的代码是否基于此变量返回2个不同的记录集(列和类型)? 如果是这样,则必须将存储的进程拆分为2

此外,我还找到了一个解释原因的答案

编辑: 将分支更改为内联代码

Set @dtSomeDate = CASE WHEN ISDATE(@vcSomeDateOrAgeInDays) = 1 THEN @vcSomeDateOrAgeInDays ELSE NULL END

谢谢你的文章参考!虽然我没有看到它解释为什么在FMTONLY模式下忽略条件语句和分支语句,但它展示了一个很好的例子,说明了如何使用FMTONLY模式来破坏安全性。。。我想我没有理解我的观点:问题是FMTONLY=ON模式可能会导致执行不应该执行的语句;这可能导致例外情况。我将继续在我的问题中插入这种情况的一个具体例子……将@dtSomeDate=case设置为ISDATE(@vcSomeDateOrAgeInDays)=1,然后将@vcSomeDateOrAgeInDays设置为NULL END?@Yarik:你能用问题的形式表达这一点吗。SQL Server文档清楚地说明SET FMTONLY ON执行所有非条件语句,所以我不确定您的问题是什么?