存储过程给出与 tsql 不同的结果集,仅在某些服务器上

2023-11-21

这是我昨天提出的问题的后续:

您是否曾经遇到过 SQL Server 2008 返回与 SQL Server 2000 不同的结果集的情况?

我最初认为存储过程在 sql2000 和 sql2008 上给出了不同的结果,但我已经做了相当多的缩小问题范围的工作,并消除了相当多的代码以将其简化为一个简单/可重现的问题。总结是,一段 TSQL 当作为 proc 运行时返回不同的答案,与作为 TSQL 运行的相同代码位不同,但仅在我的客户端服务器上,不在我的任何一个测试服务器上。

当我运行这个 SQL 时:

DECLARE @PropertyID int 
DECLARE @PortfolioID    int 
DECLARE @StartDate  datetime 
DECLARE @EndDate    datetime 
DECLARE @AcctMethod tinyint 

SET @PropertyId=3555
--SET @PortfolioId = null
SET @StartDate= '3/1/2010'
SET @EndDate='2/28/2011'
SET @AcctMethod=1

DECLARE    @ErrorMsg    varchar(70)
DECLARE @ExclAcct tinyint

SET NOCOUNT ON
CREATE TABLE #IncomeStatement (
    PropertyID      int,
    GLAccountID     int,
    SubTotalAccountID   int,
    Debits          money,
    Credits         money,
    YTDDebits       money,
    YTDCredits      money,
    PZDebits        money,
    PZCredits       money,
    AccountType     tinyint
)

--Initialize Temporary Table
INSERT INTO #IncomeStatement(PropertyID, GLAccountID, SubTotalAccountID, AccountType, Debits, Credits, YTDDebits, YTDCredits, PZDebits, PZCredits)
SELECT PropertyID, ID, SubTotalAccountID, AccountType, 0, 0, 0, 0, 0, 0
FROM ChartOfAccounts
WHERE (PropertyID = @PropertyID OR @PropertyID Is Null)
    AND (@PortfolioID is null OR PropertyID in (select PropertyID from PortfolioProperty where PortfolioID=@PortfolioID))
    AND (Category > 3 or CashFlowCode <> 0)

--Period Activity
IF @AcctMethod = 1
    SET @ExclAcct = 0
ELSE
    SET @ExclAcct = 1

UPDATE Bal
SET 
    Debits = Debits +  D.TotDebit,
    Credits = Credits +  D.TotCredit
FROM #IncomeStatement Bal
    INNER JOIN (SELECT GLAccountID, Sum(Debit) AS TotDebit, Sum(Credit) AS TotCredit
            FROM GLTransaction GT
            WHERE (GT.PropertyID = @PropertyID OR @PropertyID Is Null)
                AND AccountingMethod <> @ExclAcct 
                AND Posted = 1
                AND TranDate >= @StartDate
                AND TranDate <= @EndDate
            GROUP BY GLAccountID) AS D
        ON BAL.GLAccountID = D.GLAccountID 

select * from #IncomeStatement  where GLAccountID=11153 
drop table    #IncomeStatement

然而,当我将上述代码转换为如下存储过程时,我得到的借方金额为 124.27 美元:

   CREATE Procedure [dbo].[sp_test]
    @PropertyID int = Null,
    @PortfolioID    int = Null,
    @StartDate  datetime = Null,
    @EndDate    datetime = Null,
    @AcctMethod tinyint = 1

AS


DECLARE    @ErrorMsg    varchar(70)
DECLARE @ExclAcct tinyint

SET NOCOUNT ON
CREATE TABLE #IncomeStatement (
    PropertyID      int,
    GLAccountID     int,
    SubTotalAccountID   int,
    Debits          money,
    Credits         money,
    YTDDebits       money,
    YTDCredits      money,
    PZDebits        money,
    PZCredits       money,
    AccountType     tinyint
)

--Initialize Temporary Table
INSERT INTO #IncomeStatement(PropertyID, GLAccountID, SubTotalAccountID, AccountType, Debits, Credits, YTDDebits, YTDCredits, PZDebits, PZCredits)
SELECT PropertyID, ID, SubTotalAccountID, AccountType, 0, 0, 0, 0, 0, 0
FROM ChartOfAccounts
WHERE (PropertyID = @PropertyID OR @PropertyID Is Null)
    AND (@PortfolioID is null OR PropertyID in (select PropertyID from PortfolioProperty where PortfolioID=@PortfolioID))
    AND (Category > 3 or CashFlowCode <> 0)

--Period Activity
IF @AcctMethod = 1
    SET @ExclAcct = 0
ELSE
    SET @ExclAcct = 1

UPDATE Bal
SET 
    Debits = Debits +  D.TotDebit,
    Credits = Credits +  D.TotCredit
FROM #IncomeStatement Bal
    INNER JOIN (SELECT GLAccountID, Sum(Debit) AS TotDebit, Sum(Credit) AS TotCredit
            FROM GLTransaction GT
            WHERE (GT.PropertyID = @PropertyID OR @PropertyID Is Null)
                AND AccountingMethod <> @ExclAcct 
                AND Posted = 1
                AND TranDate >= @StartDate
                AND TranDate <= @EndDate
            GROUP BY GLAccountID) AS D
        ON BAL.GLAccountID = D.GLAccountID 

select * from #IncomeStatement  where GLAccountID=11153 
drop table    #IncomeStatement

然后像这样执行:

EXEC sp_test @PropertyID=3555, @StartDate='03/01/2010', @EndDate='02/28/2011'

我收到的借方金额为 248.54 美元,恰好是应有金额的两倍。

我真的很困惑。更奇怪的是,如果我备份这个数据库,然后将其复制到运行 sql2000 的 win2003 服务器或运行 SQL2008R2 的 win2008 服务器,它在两种情况下都能正常工作。所以seems这是导致问题的服务器或数据库设置,但已经没有什么可以检查的了 - 希望新的一双眼睛可以指出我明显遗漏的东西。


好的,这是我的修复 - 它绝对不能解释原来的问题,但这就是我所做的:

每当我遇到“参数嗅探”性能问题时,为了解决我为所有参数声明“局部”变量,将这些参数分配给这些变量,然后在过程的其余部分中仅使用局部变量,如下所示:

  ALTER Procedure [dbo].[rptDateIncomeStatementPlusCash]
        @PropertyID int = Null,
        @PortfolioID    int = Null,
        @StartDate  datetime = Null,
        @EndDate    datetime = Null,
        @AcctMethod tinyint = 1
    AS
      DECLARE   @xPropertyID    int 
      DECLARE   @xPortfolioID   int 
      DECLARE   @xStartDate datetime 
      DECLARE   @xEndDate   datetime 
      DECLARE   @xAcctMethod    tinyint 

      SET @xPropertyID= @PropertyId
      SET @xPortfolioId = @PortfolioId
      SET @xStartDate = @StartDate
      SET @xEndDate = @EndDate
      SET @xAcctMethod = @AcctMethod

相似之处在于,当参数嗅探出现问题时,您可以通过 MGMT studio 运行存储过程,并获得比将其作为 SQL 运行更好的性能,并且进行更改(如上面的更改),通常会修复它。

就我而言,我发现直接 TSQL 与执行 proc 之间存在差异(尽管它与性能无关),我尝试了一下 - 很快就成功了;我希望我有一个更好的解释,因为说实话,当我想到 SQL Server 在运行几乎相同的代码时偶尔会给出不一致的结果时,我觉得很可怕。

我确实找到了MS 的此公告关于一个类似但不同的问题,至少确实证实在正确的情况下,SQL Server 可能会给你错误的答案,并且这个相关的错误报告用这个关键词:

描述:各进行两次会话 对过程 P 的多次调用 改变参数值。这 过程 P 执行一个查询 静态数据,有时带有 OPTION (重新编译)有时没有。

有时 P 会给出不正确的结果 (对于下面的重现,这通常是 发生率约为 1/2% - 1%)。当P的结果错误时,P返回 预期数量的 0 或两倍 行数。

昨天有人留下了关于参数嗅探的可能性的评论,但无论出于何种原因,他们删除了他们的评论(或答案),所以我不能相信他们的提示。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

存储过程给出与 tsql 不同的结果集,仅在某些服务器上 的相关文章

随机推荐

  • 如何使用freopen_s函数

    为了从文本文件读取输入 我编写了以下代码 int main int x ifndef ONLINE JUDGE freopen input txt r stdin endif scanf d x printf d n x system pa
  • 为什么“git clone”不采用 refspec?

    看来很多人都去换了git clone与组合git init git fetch 这看起来相当愚蠢 不幸的是像 Jenkins 这样的工具不会为你做这件事 那么为什么 git clone 不像 git fetch 那样采用 refspec 呢
  • 如何在 Ruby 中获取 Enumerable 的第 n 个元素

    例如 要返回第 10 000 个质数 我可以编写 require prime Prime first 10000 last gt 104729 但是创建一个巨大的中间数组 只是为了检索它的最后一个元素感觉有点麻烦 鉴于 Ruby 是一种如此
  • 强制调用父方法

    是否有 或模式 强制调用父方法 我有一个像这样的抽象类 abstract class APrimitive public function validate Do some stuff that applies all classes th
  • 多个main方法有什么用?

    c 使我们能够使用方法定义多个类 Main方法是程序执行的入口点 那么为什么我们要拥有多个地方来执行程序呢 多个 main 方法相对于单个 main 方法有什么优点 Edit 示例 cs Class Example 1 public sta
  • 打字稿用只读属性初始化对象

    有没有办法初始化对象文字并同时声明其具有只读属性的接口 例如 let a readonly b 2 readonly c 3 您可以使用as const断言 let a b 2 c 3 as const typed as readonly
  • 为什么我的异步 ASP.NET Web API 控制器阻塞主线程?

    我有一个 ASP NET Web API 控制器thought将异步操作 控制器设计为在第一个请求时休眠 20 秒 但立即为任何后续请求提供服务 所以我预计的时间表是这样的 提出要求1 提出要求2 提出要求3 要求 2 次退货 请求 3 个
  • 如何在 Ruby 中交错不同长度的数组

    如果我想在 Ruby 中交错一组数组 并且每个数组的长度相同 我们可以这样做 a zip b zip c flatten 但是 如果数组的大小可以不同 我们如何解决这个问题呢 我们可以做这样的事情 def interleave args r
  • UITextView - 根据 SwiftUI 中的内容调整大小

    我试图弄清楚如何使 UITextView 的大小取决于它在 SwiftUI 中的内容 我将 UITextView 包裹在UIViewRepresentable如下 struct TextView UIViewRepresentable Bi
  • 如何以编程方式截取屏幕截图(Swift、SpriteKit)

    我尝试了建议的方法 但输出是白色的空白屏幕截图 这让我假设我没有在视图中添加任何内容 以下是我向视图添加图形的方法 addChild 方法随 SpriteKit 一起提供 它接受 SKSpriteNodes addChild backgro
  • 为什么安装 Visual Studio 2008 后,catch(TException) 处理块行为在调试器下有所不同?

    考虑下面的控制台应用程序 该应用程序具有一个带有通用捕获处理程序的方法 用于捕获类型的异常TException 当此控制台应用程序使用 调试 配置构建并在 Visual Studio 调试器下执行 即通过 vshost exe 时 在 Vi
  • h1 标签类别(备用)

    我知道 h1 标签对于 SEO 很重要 所以我所有的标题都是 H1 太棒了 现在 我需要在某些页面上有一个稍微不同的标题 作为文本的第一行 通常 我只是将 h1 复制为 h2 并交替 问题 是否可以在标题标签中添加一个类 我尝试过但没有成功
  • 是否可以在handlebars.js模板中使用JavaScript

    描述说明了一切 如何将 JavaScript 脚本放入车把模板中 我想为我的网站制作一个动态 Paypal 按钮
  • PyQt5:对象没有属性“连接”

    我目前正在关注thisPyQt 中线程的教程 代码来自here 由于它是用 PyQt4 和 Python2 编写的 因此我调整了代码以使其能够与 PyQt5 和 Python3 一起使用 这是 gui 文件 newdesign py cod
  • 优化 ORDER BY

    我正在尝试优化这个排序查询posts by reputation字段 第一个 然后id场 第二 如果没有第一个字段查询 则需要约 0 250 秒 但如果有第一个字段查询 则需要约 2 500 秒 意味着慢了 10 倍 太糟糕了 有什么建议吗
  • 我可以得到Python中“print”语句的输出吗?

    pythonw exe 没有控制台 所以我看不到 print 的输出 但我的程序在 python exe 中正常 在 pythonw exe 中失败 我只想查看 python 解释器的日志和我的 print 语句打印的日志 这可行吗 您可以
  • 如何将 Nginx IP 附加到 Kubernetes Nginx Ingress Controller 中的 X-Forwarded-For

    我想知道 如何将 Nginx IP 附加到 X Forwarded For 我在 Ingress 注释中添加了片段 apiVersion networking k8s io v1beta1 kind Ingress metadata nam
  • 适用于字节数组的哈希码方法?

    数组的最佳哈希方法是什么byte 这些数组是序列化的类对象 包含通过 TCP IP 在应用程序之间传递的 jpeg 图像 数组大小约为200k 任何内置的散列函数都可以 根据您对碰撞的关心程度 您可以选择以下选项 从最多碰撞到最少碰撞 MD
  • 托管在不同域上的 JavaScript 可以读取/修改另一个域的 DOM 吗?

    我有一个关于托管在域 例如 CDN 的域 例如 example com 上但从不同域 例如 example net 下的网站加载的 JavaScript 的潜在安全问题 限制的问题 现在想象一下 加载的 JavaScript 将仅读取 修改
  • 存储过程给出与 tsql 不同的结果集,仅在某些服务器上

    这是我昨天提出的问题的后续 您是否曾经遇到过 SQL Server 2008 返回与 SQL Server 2000 不同的结果集的情况 我最初认为存储过程在 sql2000 和 sql2008 上给出了不同的结果 但我已经做了相当多的缩小