2012-03-12 36 views
5

我有一個複雜的數據視圖,遞歸鏈接和總結信息。如何忽略數據視圖中的「算術溢出」相關錯誤?

每天晚上,計劃任務運行一個存儲過程,該過程從數據視圖中選擇所有數據,並將其插入表中,以便用戶可以比在數據上運行select語句更快地查詢和分析數據視圖。

父表由幾十萬條記錄組成,而導出的結果集大小超過1,000,000條記錄。

對於大多數夜晚來說,出口過程沒有任何問題,但是,如果用戶在我們的主ERP系統中輸入了錯誤的值,則會導致夜間過程崩潰,因爲其中一個小數字段將包含一個不適合我必須對數據進行的某些轉換。調試和查找特定的,錯誤的字段可能非常困難和耗時。

說了這麼多,我已經讀了關於兩個SQL設置NUMERIC_ROUNDABORTARITHABORT。這些聽起來像是解決我的問題的完美選擇,但是,我似乎無法讓他們使用我的數據視圖或存儲過程。

我的存儲過程只不過是一個TRUNCATE和INSERT語句。我追加...

SET NUMERIC_ROUNDABORT OFF 
SET ARITHABORT OFF 

...到SP的開頭,並沒有幫助。我認爲這是因爲錯誤在技術上發生在與數據視圖相關的代碼中。

接下來,我試圖向數據視圖中添加兩個擴展屬性,希望這會起作用。它沒有。

有沒有一種方法可以將這些SQL屬性設置爲忽略舍入錯誤,以便我可以從數據視圖中導出數據?

我知道我們大多數人,作爲SO回答者,我們的第一個傾向是要求代碼。然而,在這種情況下,代碼既非常複雜又專有。我知道修復造成偶然溢出的定義是最理想的解決方案,但在這種情況下,忽略這些類型的錯誤要高效得多,因爲它們發生在罕見的基礎上,並且難以排除故障。

如何忽略此行爲?

UPDATE

一次偶然的機會,我相信我可能已經找到了問題的根源,但是,我不知道爲什麼會發生。它從那以後就沒有了。

通過我的表格視圖,我有各種領域的計算。由於這些字段需要適合表格中定義爲decimal (12, 5)的字段,因此我總是將視圖字段語句包裝在​​子句中。

偶然,我偶然發現了一個奇怪的事情。我決定看看SSMS如何「看到」我的數據視圖。在SSMS對象資源管理器中,我擴展了Views - > [My View] -Columns部分,我看到其中一個字段被定義爲decimal (13, 5)

我認爲我必須在我的一個演員陳述中犯了一個錯誤,但是在整個表視圖的代碼中搜索後,decimal(13, 5)字段沒有定義?!我唯一的猜測是,SSMS所看到的視野的定義必須來自結果數據。然而,我不知道這是如何發生的,因爲我將每個字段都設置爲decimal(12, 5)

我想知道爲什麼會發生這種情況,但我的原始問題仍然存在。我可以在一個表視圖上定義如何和什麼SET語句,它將忽略所有的算術溢出,並在包含錯誤數據的字段中寫入一個空值?

最後意見

我已標記HeavenCore的作爲應答響應,因爲它沒有解決我的問題,但它並沒有解決我的根本問題。

經過一些故障排除並試圖讓我的導出工作,我將不得不嘗試一種不同的方法。即使將NUMERIC_ROUNDABORTARITHABORT屬性設置爲OFF,我仍然無法使導出工作。

+0

對於這個被髮生的值必須得到轉換爲不同的數據類型,從它被存儲在哪裏?假設是這種情況,是在插入級別或插入級別之前選擇是否進行投射?例如 - 如果您從中手動選擇一些流氓數據,該視圖是否會生成錯誤? (例如,你是否在視圖中將一列轉換爲INT - 溢出可能發生在那裏而不是插入?) - 如果視圖選擇正常,則可以修改INSERT ... SELECT語句以排除基於LEN的某些值()? – HeavenCore 2012-03-12 15:26:38

+0

如果您從數據視圖中選擇數據,則會發生錯誤。數據視圖中有強制轉換語句。這個強制轉換是強制性的,在所有算術發生後都會發生。 – RLH 2012-03-12 15:41:04

+0

如果您現在忽略VIEW並在SET NUMERIC_ROUNDABORT OFF&SET ARITHABORT OFF設置下手動運行SELECT語句,那麼查詢是否工作? (請注意,當您打開一個新的查詢窗口時,SSMS會隱式設置這些設置,請檢查SSMS選項) – HeavenCore 2012-03-12 16:09:56

回答

4

我認爲ARITHABORT是你的朋友在這裏。

例如,使用SET ARITHABORT OFF & SET ANSI_WARNINGS OFF將null,則無法施放(而不是拋出異常)

這裏的值是一個簡單的例子:

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[tbl_OverflowExample](
    [Value] [decimal](12, 2) NULL 
) ON [PRIMARY]  
GO 
INSERT [dbo].[tbl_OverflowExample] ([Value]) VALUES (CAST(9999999999.00 AS Decimal(12, 2))) 
GO 
INSERT [dbo].[tbl_OverflowExample] ([Value]) VALUES (CAST(1.10 AS Decimal(12, 2))) 
GO 

--#### Select data without any casting - works 
SELECT VALUE 
FROM dbo.tbl_OverflowExample 

--#### With ARITHABORT and ANSI warnings disabled - Returns NULL for 999999 but 1.10 as expected 
SET ARITHABORT OFF; 
SET ANSI_WARNINGS OFF; 
SELECT CONVERT(DECIMAL(3, 2), VALUE) 
FROM dbo.tbl_OverflowExample 
GO 

--#### With defaults - Fails with overflow exception 
SET ARITHABORT ON; 
SET ANSI_WARNINGS ON; 
SELECT CONVERT(DECIMAL(2, 2), VALUE) 
FROM dbo.tbl_OverflowExample 

個人,但 - 我寧願調試視圖並使用一些CASE /.../ END語句返回NULL如果底層值大於目標數據類型 - 這將確保視圖工作,而不管連接選項如何。

編輯:糾正了一些事實錯誤

+0

你可以添加一個「萬一你必須使用這些設置」部分?我的問題是我無法弄清楚如何在視圖中定義一個'SET'語句。是的,你是對的。假字段將返回一個NULL值。但就這些數據而言,重要的是它每天都可用,但這些數據主要用於近似估計,並且有1,000,000條返回的記錄,如果1幾個月內幾個星期不正確,那麼也可以。 – RLH 2012-03-12 17:34:03

+0

你說select從select中插入是從一個sceduled任務運行的?在運行EXEC命令之前,您只需修改任務以調用「SET ARITHABORT OFF;'&'SET ANSI_WARNINGS OFF;'。假設SQL Server代理作業,您將有1步驟,如下所示:SET ARITHABORT OFF; SET ANSI_WARNINGS OFF; EXEC usp_Whatever;' – HeavenCore 2012-03-12 17:36:42

+0

另外,我已經嘗試了很多你的建議。問題是我通常可以找到失敗的特定行,但是我無法在數學中找到失敗點,或者無法找到哪個列。在這個視圖中有很多公式和演員陳述。許多演說都是爲了防止這種事情發生,但它每6個月就會爬上一次。查找問題行並修復它可能需要一整天的時間,修復底層數據並不重要。這就是爲什麼我願意忽略這些錯誤,如果可能的話。 – RLH 2012-03-12 17:39:13

相關問題