2011-04-26 23 views
7

这是一个后续的问题,我昨天问:存储过程给出了不同的结果集比TSQL,仅在某些服务器

Have you ever had SQL Server 2008 return a different result set than SQL Server 2000?

,我本来以为存储过程是给在SQL2000不同的充结果与sql2008相比,但我已经做了相当多的缩小问题的范围,并且消除了很多代码以将其归结为简单/可重现的问题。总结是,一个TSQL作为proc运行时会返回一个不同的答案,即只有TSQL,才运行相同的代码,但只能在我的客户机服务器上运行,而不是在任一个测试服务器上运行。

当我运行这个TSQL:

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 [email protected])) 
    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 [email protected])) 
    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 

,然后执行它loke:

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

我得到一个248.54美元的借记金额,这应该是它的两倍。

我真的难住了。奇怪的是,如果我备份这个数据库,然后将其复制到运行sql2000的win2003服务器或运行SQL2008R2的win2008服务器,它在两种情况下都能正常工作。所以,它似乎它是一个服务器或数据库设置,导致问题,但已用完检查的东西 - 希望一组新的眼睛可以指出我明显缺少的东西。

+0

哇,怪异的行为。 – alex 2011-04-26 21:03:03

+0

这真的很奇怪。您能否告诉您在两种情况下是否在#IncomeStatement中使用相同数量的记录?另外,你是否尝试过使用表变量而不是临时表?也许有一个客户端服务器上的tempdb设置会导致一些奇怪的现象。 – rsbarro 2011-04-26 21:15:44

+0

您是否检查SET ANSI_NULLS是否有所作为? http://msdn.microsoft.com/en-us/library/ms188048.aspx – 2011-04-26 21:58:41

回答

7

OK,这里是我的修复 - 它绝对不会无法解释最初的问题,但是这是我做过什么:

每当我有一个“参数嗅探”性能问题,为了解决我声明所有参数的“本地”变量,分配这些参数到这些变量,然后只使用局部变量在proc的其余部分,像这样:

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工作室,并获得比运行它作为SQL更好的性能,并且改变(如上所述),通常盟友解决它。在我的情况下,我看到直TSQL与执行过程(虽然它不是性能相关)之间的区别,我试了一下 - 并presto它的工作;我希望我有一个更好的解释,因为老实说,我觉得可怕的是,当运行几乎相同的代码时,SQL服务器会出现不一致的结果。

我没有找到this bulletin from MS有关类似,但不同的问题,至少也证实,在适当的情况下,SQL Server可能会给你坏的答案,this related bug report这个关键的一句:

说明:两张每个会话都会使 多次调用过程P, 会更改参数值。过程P对 静态数据执行一个查询,有时使用OPTION (RECOMPILE),有时不使用。有时P会给出不正确的结果 (对于下面的报告,这通常是 发生的时间约为1/2%-1%)。 当P的结果是错误的,P返回 0或两倍于行的预期数 。

有人昨天离开有关参数嗅探的可能性发表评论,但无论出于何种原因,他们删除他们的评论(或答案),所以我不能对他们给予信贷的小费。

+0

我们有一个程序,可以生成一个公司在一个国家使用乐透算法的可能匹配程序,在这个算法中,他们被要求返回50%的数学回归彩票游戏的客户。我们在查询时遇到的一个问题是,如果我们直接运行存储过程,它不会返回任何低于80%的结果,但如果我们在SSMS中突出显示该块并运行它,则会得到更好的值分布。我们没有改变参数值,但是做了这里的工作 - 创建新的变量并赋值 - 完美无缺地工作。 **谢谢!** – 2016-10-10 13:48:00

1

Here is the execution plan, for those interested - could figure out how do this as a comment

+0

这是回应上面的意见寻找执行计划 - 无法将其添加为评论。 – 2011-04-27 18:54:05

+1

不知道你是否碰到了一个错误并发的问题 - 使用2个并发线程处理相同的数据或者其他东西。看起来像[一些paralellism错误](http://support.microsoft.com/kb/888799)在SQL Server 2000 SP4中修复,但我看不到一个看起来很清楚的相关。 – 2011-04-28 10:37:08

相关问题