2011-04-26 23 views
7

Đây là một followup cho một câu hỏi tôi hỏi ngày hôm qua:proc lưu trữ cho tập kết quả khác với TSQL, chỉ có trên một số máy chủ

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

nơi tôi ban đầu nghĩ rằng các thủ tục lưu trữ đã được đưa ra kết quả differnt trên SQL2000 so với sql2008, nhưng tôi đã thực hiện thu hẹp hơn một chút vấn đề và loại bỏ khá nhiều mã để làm cho nó trở thành một vấn đề đơn giản/có thể tái sản xuất. Tóm tắt là, một phần của TSQL khi chạy như một proc trả về một câu trả lời khác nhau mà cùng một chút mã chạy như chỉ TSQL, nhưng chỉ trên máy chủ khách hàng của tôi, không phải trên một trong các máy chủ thử nghiệm của tôi.

Khi tôi chạy TSQL này:

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 

tôi nhận được một số lượng thẻ ghi nợ của $ 124,27, tuy nhiên, khi tôi quay đoạn code trên vào một thủ tục lưu trữ như thế này:

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 

và sau đó thực hiện nó loke:

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

Tôi nhận được số tiền ghi nợ là 248,54 đô la, gấp đôi số tiền đó.

Tôi thực sự bối rối. Điều odder, là nếu tôi sao lưu cơ sở dữ liệu này, và sau đó sao chép nó vào một trong hai máy chủ win2003 của tôi chạy sql2000, hoặc máy chủ win2008 của tôi chạy SQL2008R2, nó hoạt động chính xác trong cả hai trường hợp. Vì vậy, nó có vẻ như nó là một máy chủ hoặc thiết lập cơ sở dữ liệu đó gây ra vấn đề, nhưng đã hết những thứ để kiểm tra - hy vọng một bộ mắt mới có thể chỉ ra một cái gì đó rõ ràng tôi đang mất tích.

+0

Hành vi lạ, lạ. – alex

+0

Điều đó thực sự kỳ quặc. Bạn có thể cho biết liệu bạn có bắt đầu với cùng số lượng bản ghi trong #IncomeStatement trong cả hai trường hợp không? Ngoài ra, bạn đã thử sử dụng biến bảng thay vì bảng tạm thời chưa? Có lẽ có một thiết lập trên tempdb trên máy chủ khách hàng đang gây ra một số sự kỳ lạ ở đây. – rsbarro

+0

Bạn đã kiểm tra xem SET ANSI_NULLS có tạo sự khác biệt không? http://msdn.microsoft.com/en-us/library/ms188048.aspx –

Trả lời

7

OK, đây là sửa chữa của tôi - nó hoàn toàn không không giải thích được vấn đề gốc, nhưng điều này là những gì tôi đã làm:

Bất cứ khi nào tôi có một "thông số đánh hơi" vấn đề hiệu suất, để giải quyết mà tôi khai báo các biến 'địa phương' cho tất cả các thông số, gán các tham số để các biến, và sau đó chỉ sử dụng các biến địa phương trong phần còn lại của proc, như thế này:

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 

sự giống nhau là khi tham số sniffing là một vấn đề , bạn có thể chạy một proc được lưu trữ qua MGMT studio và nhận được hiệu suất tốt hơn so với chạy nó như là một SQL, và thay đổi (như những ở trên), usu đồng minh sửa chữa nó.

Trong trường hợp của tôi, tôi đã thấy sự khác biệt giữa TSQL thẳng so với thực hiện proc (mặc dù nó không liên quan đến hiệu năng), tôi đã thử - và nó đã hoạt động; Tôi muốn tôi có một lời giải thích tốt hơn, bởi vì khá trung thực tôi thấy nó đáng sợ khi nghĩ rằng máy chủ SQL sẽ thỉnh thoảng cho kết quả không phù hợp khi chạy mã gần như giống hệt nhau.

tôi đã tìm this bulletin from MS về một vấn đề tương tự nhưng khác nhau, ít nhất không xác nhận rằng theo đúng trường hợp, SQL server có thể cung cấp cho bạn câu trả lời xấu, và this related bug report với cụm từ khóa này:

Mô tả: Hai mỗi phiên thực hiện nhiều cuộc gọi đến thủ tục P với thay đổi giá trị tham số. Thủ tục P thực hiện một truy vấn đối với dữ liệu tĩnh, đôi khi với OPTION (GHI CHÚ) và đôi khi không có.

Thỉnh thoảng P cho kết quả không chính xác (đối với repro dưới đây, điều này thường là xảy ra khoảng 1/2% - 1% thời gian). Khi kết quả của P sai, P trả lại hoặc bằng 0 hoặc gấp hai lần số dự kiến ​​ hàng.

Có người hôm qua đã để lại một nhận xét về thông số đánh hơi như một khả năng nhưng vì lý do gì họ xóa bình luận của họ (hoặc câu trả lời) vì vậy tôi không thể cung cấp tín dụng cho họ là hoàn toàn.

+0

Chúng tôi có một thủ tục tạo ra các kết quả phù hợp cho một thuật toán xổ số được sử dụng bởi một công ty ở một quốc gia nơi họ được yêu cầu phải trả về toán học, 50% trở lại tất cả khách hàng cho trò chơi xổ số. Một vấn đề mà chúng tôi có với truy vấn là nếu chúng tôi chạy proc được lưu trữ trực tiếp, nó sẽ không trả lại bất kỳ kết quả nào dưới 80%, nhưng nếu chúng tôi đánh dấu khối trong SSMS và chạy nó, chúng tôi sẽ phân phối giá trị tốt hơn nhiều. Chúng tôi đã không thay đổi các giá trị tham số, nhưng làm những gì ở đây - tạo ra các vars mới và gán các giá trị - làm việc hoàn hảo. ** Cảm ơn bạn! ** –

1

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

+0

Điều này là để trả lời nhận xét ở trên tìm kiếm kế hoạch thực hiện - không thể thêm nó làm nhận xét. –

+1

Tự hỏi nếu bạn nhấn một lỗi với sự phù hợp - Với 2 chủ đề đồng thời, cả hai xử lý cùng một dữ liệu hoặc một cái gì đó. Hình như đã có [một vài lỗi paralellism] (http://support.microsoft.com/kb/888799) cố định trong SQL Server 2000 SP4 nhưng tôi không thể nhìn thấy một cái nhìn rõ ràng liên quan. –

Các vấn đề liên quan