2012-03-12 13 views
5

Mam złożony widok danych, który rekursywnie łączy i podsumowuje informacje.Jak mogę zignorować błędy związane z "Przepełnieniem arytmetycznym" w widoku danych?

Każdej nocy zaplanowane zadanie uruchamia procedurę przechowywaną, która wybiera wszystkie dane z widoku danych i wstawia je do tabeli, dzięki czemu użytkownicy mogą wykonywać zapytania i analizować dane znacznie szybciej niż przy uruchamianiu instrukcji select na danych widok.

Tabela nadrzędna składa się z kilkuset tysięcy rekordów, a zestaw wyników z eksportu ma ponad 1 000 000 rekordów.

Dla większości nocy proces eksportu działa bez problemów, jednak jeśli użytkownik wprowadzi niepoprawną wartość w naszym głównym systemie ERP, spowoduje awarię procesu nocnego, ponieważ jedno z pól dziesiętnych będzie zawierać wartość, która nie pasuje do niektórych konwersji, które muszę wprowadzić w danych. Debagowanie i znajdowanie konkretnego błędnego pola może być bardzo trudne i czasochłonne.

Powiedziawszy to, przeczytałem o dwóch ustawieniach SQL NUMERIC_ROUNDABORT i ARITHABORT. Te dźwięki są idealną opcją rozwiązania mojego problemu, jednak nie mogę sprawić, by działały z moim widokiem danych lub procedurą składowaną.

Moja procedura składowana to nic innego jak instrukcja TRUNCATE i INSERT. Dołączyłem ...

SET NUMERIC_ROUNDABORT OFF 
SET ARITHABORT OFF 

... na początek SP, co nie pomogło. Zakładam, że dzieje się tak dlatego, że błąd jest technicznie przeprowadzany z poziomu kodu powiązanego z widokiem danych.

Następnie próbowałem dodać dwie rozszerzone właściwości do widoku danych, mając nadzieję, że to zadziała. Tak nie było.

Czy istnieje sposób, w jaki mogę ustawić te właściwości SQL, aby ignorowały błędy zaokrąglania, aby można było eksportować moje dane z widoku danych?

Wiem dla większości z nas, jako TAKICH ODBIORCÓW, naszą pierwszą skłonnością jest prosić o kod. W tym przypadku kod jest jednak niezwykle złożony i zastrzeżony. Wiem, że ustalenie definicji, które powodują sporadyczne przepełnienie, jest najbardziej idealnym rozwiązaniem, ale w takich okolicznościach skuteczniejsze jest po prostu ignorowanie tego rodzaju błędów, ponieważ zdarzają się one na tak rzadkich podstawach i są tak trudne do rozwiązania.

Co mogę zrobić, aby zignorować to zachowanie?

UPDATE

Przez przypadek, wierzę, że mogę odkryli przyczynę problemu, jednak nie mam pojęcia, dlaczego miałoby to mieć miejsce. Po prostu tak nie robi.

W widoku my table mam różne pola, które są obliczane. Ponieważ te pola muszą pasować do pól w tabeli, które są zdefiniowane jako decimal (12, 5), zawsze zawijam instrukcje pola widoku w klauzulach CAST(... AS DECIMAL(12, 5)).

Przypadkiem natknąłem się na osobliwość. Postanowiłem zobaczyć, jak SSMS "widział" mój widok danych. W Eksploratorze obiektów SSMS rozszerzyłem sekcję Widoki -> [Mój widok] - kolumny i zobaczyłem, że jedno z pól zostało zdefiniowane jako decimal (13, 5).

Zakładam, że popełniłem błąd w jednym z moich oświadczeń, ale po przeszukiwaniu całego kodu widoku tabeli nie ma definicji pola decimal(13, 5) ?! Przypuszczam tylko, że definicja, którą SSMS widzi w polu widoku, musi pochodzić z wynikowych danych. Jednak nie mam pojęcia, jak to się mogło stać, ponieważ każdy z pól ma wartość decimal(12, 5).

Chciałbym wiedzieć, dlaczego tak się dzieje, ale moje pierwotne pytanie nadal jest aktualne. Jak i co instrukcja SET można zdefiniować w widoku tabeli, który zignoruje wszystkie przepełnienia arytmetyczne i napisz pustą wartość w polach z błędnych danych?

UWAGI KOŃCOWE

Zaznaczyłem odpowiedź HeavenCore jako odpowiedź, ponieważ nie kieruję moje pytanie, ale nie rozwiązać mój podstawowy problem.

Po drobnych problemach i próbach wprowadzenia eksportu do pracy, muszę spróbować zastosować inne podejście. Nadal nie mogę uruchomić eksportu, nawet jeśli ustawię właściwości NUMERIC_ROUNDABORT i ARITHABORT na OFF.

+0

Aby tak się dziać wartość musi być coraz oddanych do innego typu danych, z której jest zapisane? Zakładając, że tak jest, czy odlewanie odbywa się na poziomie wstawki, czy wybierz przed wstawieniem? Na przykład - czy widok generuje błąd, jeśli wybierzesz z niego ręcznie jakieś nieuczciwe dane? (na przykład czy przesyłasz kolumnę do wartości INT w widoku - może występować przepełnienie w przeciwieństwie do wstawki?) - Jeśli widok dobrze się wybiera, możesz zmienić instrukcję INSERT ... SELECT, aby wykluczyć określone wartości na podstawie LEN()? – HeavenCore

+0

Błąd występuje, jeśli WYBIERZ dane z widoku danych. Istnieją instrukcje rzutowania w widoku danych. Odlewanie to jest obowiązkowe i dzieje się po wykonaniu wszystkich działań arytmetycznych dla pola. – RLH

+0

Jeśli teraz zignorujesz WIDOK i uruchomisz instrukcję SELECT w widoku ręcznie przy ustawieniu 'USTAW NUMERIC_ROUNDABORT OFF' i' USTAW ARITHABORT OFF', czy zapytanie działa? (zauważ, że SSMS ustawia te ustawienia niewidocznie po otwarciu nowego okna zapytania, sprawdź opcje SSMS). – HeavenCore

Odpowiedz

4

Myślę, że ARITHABORT jest tu twoim przyjacielem.

Na przykład, używając SET ARITHABORT OFF & SET ANSI_WARNINGS OFF będzie NULL wartości nie udaje mu się rzucić (zamiast rzucania wyjątkami)

Oto krótki przykład:

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 

Osobiście choć - wolałbym, aby debugowanie widoku i użycie niektórych instrukcji o wartości CASE /.../ END do zwrócenia wartości NULL, jeśli wartość bazowa jest większa niż docelowy typ danych - zapewniłoby to działanie działa niezależnie od opcji połączenia.

EDIT: Poprawiono kilka błędów rzeczowych

+0

Czy możesz dodać sekcję "Na wszelki wypadek musisz użyć tych ustawień"? Mój problem polega na tym, że nie potrafię zdefiniować instrukcji 'SET' w widoku. Tak, masz rację. Pola fałszywe zwrócą wartość NULL. Ale w przypadku tych danych ważne jest, aby były one dostępne każdego dnia, ale dane te są wykorzystywane głównie do ścisłych szacunków i z 1 000 000 zwracanych rekordów, to jest OK, jeśli 1 jest nieprawidłowy przez kilka tygodni, co kilka miesięcy. – RLH

+0

Mówisz, że insert z select wybierany jest z zadania sceduled?po prostu trzeba zmodyfikować zadanie, aby wywołać 'USTAW ARITHABORT OFF;' & 'USUŃ ANSI_WARNINGS OFF;' przed uruchomieniem polecenia EXEC. Zakładając zadanie agenta SQL Server, będziesz miał 1 krok w następujący sposób: 'USTAW ARITHABORT OFF; USTAW ANSI_WARNINGS OFF; EXEC usp_Whatever; ' – HeavenCore

+0

Próbowałem również wielu twoich sugestii. Problem polega na tym, że zwykle mogę znaleźć konkretny wiersz, który się nie powiedzie, ale nie mogę znaleźć punktu awarii w matematyce lub koniecznie w tej kolumnie. W tym widoku istnieje wiele formuł i instrukcji rzutowania. Wiele z tych oświadczeń ma zapobiegać temu, aby coś takiego się wydarzyło, a mimo to skrada się mniej więcej raz na 6 miesięcy. Znajdowanie wiersza z problemem i jego poprawianie może zająć nawet jeden pełny dzień, a poprawienie podstawowych danych nie jest tak ważne. Dlatego wolę ignorować te błędy, jeśli w ogóle możliwe. – RLH

Powiązane problemy