Как можно игнорировать ошибки, связанные с «арифметическим переполнением» из представления данных? - PullRequest
5 голосов
/ 12 марта 2012

У меня сложное представление данных, которое рекурсивно связывает и суммирует информацию.

Каждую ночь запланированное задание запускает хранимую процедуру, которая выбирает все данные из представления данных и вставляет их в таблицу, чтобы пользователи могли запрашивать и анализировать данные намного быстрее, чем выполнение оператора выбора в представлении данных. .

Родительская таблица состоит из нескольких сотен тысяч записей, а размер набора результатов экспорта превышает 1 000 000 записей.

В течение большинства ночей процесс экспорта работает без каких-либо проблем, однако, если пользователь введет неверное значение в нашей основной системе ERP, он завершит работу ночного процесса, поскольку одно из десятичных полей будет содержать значение, которое не подходит в некоторых из преобразований, которые я должен сделать на данных. Отладка и поиск определенного, ошибочного поля может быть очень трудоемким и длительным.

С учетом сказанного я прочитал о двух настройках SQL NUMERIC_ROUNDABORT и ARITHABORT. Это похоже на идеальные варианты решения моей проблемы, однако я не могу заставить их работать ни с моим представлением данных, ни с хранимой процедурой.

Моя хранимая процедура - не что иное, как оператор TRUNCATE и INSERT. Я добавил ...

SET NUMERIC_ROUNDABORT OFF
SET ARITHABORT OFF

... к началу SP, и это не помогло. Я предполагаю, что это потому, что технически ошибка происходит из-за кода, связанного с представлением данных.

Затем я попытался добавить два расширенных свойства в представление данных, надеясь, что это сработает. Это не так.

Есть ли способ, которым я могу установить эти свойства SQL, чтобы игнорировать ошибки округления, чтобы я мог экспортировать свои данные из своего представления данных?

Я знаю, что для большинства из нас, как SO, отвечающих, наша первая склонность - запрашивать код. В этом случае, однако, код является чрезвычайно сложным и запатентованным. Я знаю, что исправление определений, которые вызывают случайное переполнение, является наиболее идеальным решением, но в этом случае гораздо эффективнее просто игнорировать ошибки такого типа, потому что они случаются так редко и их трудно устранить.

Что я могу сделать, чтобы игнорировать это поведение?

UPDATE

Случайно, я думаю, что, возможно, нашел основную причину проблемы, однако я понятия не имею, почему это происходит. С тех пор просто не получается.

В моем табличном представлении у меня есть различные поля, которые рассчитываются. Поскольку эти поля должны помещаться в полях таблицы, которые определены как decimal (12, 5), я всегда заключаю операторы полей представления в предложения CAST( ... AS DECIMAL(12, 5)).

Случайно я наткнулся на странность. Я решил посмотреть, как SSMS «увидела» мое представление данных. В обозревателе объектов SSMS я развернул раздел Views -> [My View] -Columns и увидел, что одно из полей было определено как decimal (13, 5).

Я предположил, что, должно быть, допустил ошибку в одном из своих операторов приведения, но после поиска по всему коду для табличного представления нет определения для поля decimal(13, 5) ?! Я могу только предположить, что определение, которое SSMS видит для поля представления, должно быть получено из результирующих данных. Тем не менее, я понятия не имею, как это могло произойти, так как я каждое поле к decimal(12, 5).

Я хотел бы знать, почему это происходит, но, опять же, мой первоначальный вопрос остается в силе. Как и какой оператор SET можно определить в табличном представлении, которое будет игнорировать все арифметические переполнения и записывать нулевое значение в полях с ошибочными данными?

ЗАКЛЮЧИТЕЛЬНЫЕ КОММЕНТАРИИ

Я отметил ответ HeavenCore как ответ, потому что он действительно отвечает на мой вопрос, но не решил мою основную проблему.

После небольшого устранения неполадок и попыток заставить мой экспорт работать, мне придется попробовать другой подход. Я все еще не могу заставить экспорт работать, даже если для свойств NUMERIC_ROUNDABORT и ARITHABORT установлено значение OFF.

1 Ответ

4 голосов
/ 12 марта 2012

я думаю 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, если базовое значение больше, чем целевой тип данных - это обеспечит работу представления независимо от параметров подключения.

РЕДАКТИРОВАТЬ: Исправлены некоторые фактические ошибки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...