2009-12-21 1 views
0

В нашем приложении мы будем позволять пользователям вводить арифметические выражения (+ - * /), используя другие столбцы базы данных для чисел, которые затем анализируются приложением и записываются в базу данных в виде вычисленного столбца.Проверить арифметические переполнения в вычисленных столбцах?

Однако возникают проблемы, связанные с тем, что пользователи могут создавать выражения, которые могут вызывать исключения, когда вы используете select * таблицу, такую ​​как деление на ноль, арифметическое переполнение и возможные другие, с которыми я еще не сталкивался (хотя I думаю это все из них).

Наличие базы данных исключение на select * было бы абсолютно разрушительным. Я предпочел бы переписать свое выражение во что-то, что не удавалось бы изящно, если бы они подвергли ошибкам данные.

Для деления на нуль решения довольно прост:

add [Col] as case {divisor} when 0 then N'DIVIDE-BY-ZERO' else {expression} end 

Мой вопрос: что я могу сделать для арифметического переполнения? Отображение койки или явно неправильных данных в столбце не будет проблемой, но исключение будет исключать.

+1

Как вы хотите обрабатывать случай, когда пользователь вводит значения в столбцах, которые приведут к сбою вычисленного столбца на основе значений в этих столбцах? Вы хотите предотвратить вставку или обновление? –

+0

Абсолютно нет. Поскольку у нас есть разные клиенты, у которых есть разные способы продвижения своего бизнеса, наше приложение имеет около десятка различных способов вставки/обновления данных, начиная от входа в приложение и ввода текста в текстовые поля в фоновый сервис, который захватывает файлы Excel. Модификация всего, чтобы предотвратить плохие данные, была бы вполне инженерным проектом ... – Tinister

ответ

1

Ненавижу видеть, что вы принимаете ответ, который на самом деле не приближает вас к вашей цели.

В качестве отдельного ответа, который может немного помочь вам, вы можете использовать вычисленные столбцы (детерминированный) скалярный UDF.

См, например, here

Так что, если вы собираетесь создать вычисляемый столбец, сделать его передать столбцы в сгенерированном UDF (UDF, или нескольких) и сделать работу там. В скалярном UDF у вас может быть много кода, чтобы поймать проблемы, но вы все еще не можете использовать TRY/CATCH. То, что вы можете сделать в скалярном UDF, - это зависание и возврат соответствующих ответов (возможно, пузырьки NULL).

Но производительность будет очень бедных на скалярные UDF, (не уверен, не сохранялось встроенные вычисляемых столбцов по сравнению с UDF, мы в основном используем сохранялось), так что вы могли бы серьезно рассмотреть вопрос о внесении столбец сохраняется, который затем использовать пространство в базе данных и делать вставки и обновления немного медленнее. Это большой компромисс.

0

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

На исключениях, вы можете вернуть результат нонсенса набор, который совместит с оригинальным определенным пользователемом один:

begin try 
    select exp(999) 
end try 
begin catch 
    select 1 
end catch 
+0

Да, это, безусловно, будет весело. Проблема с использованием исключений заключается в том, что мы внедрили стороннее программное обеспечение, которое напрямую взаимодействует с базой данных (часть приложения, которое мы пишем, является сборкой базы данных), поэтому я бы скорее построил решение прямо в таблице , если вообще возможно. Спасибо за идею, хотя! – Tinister

1

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

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

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

Поймать исключение, используя TRY/CATCH - это сценарий «все или ничего», а не строка за строкой.

+0

Hrm. Что вы думаете о том, чтобы скомпилировать его в триггер ПОСЛЕ UPDATE? По-вашему, это будет законное использование триггера? – Tinister

+0

Нет. Зачем делать это в базе данных хорошей идеей? В любом случае я не хочу, чтобы кто-то делал SELECT *. Я даже не позволяю пользователям делать SELECT, если я могу избежать этого, и обычно не на TABLE (возможно, VIEW), так как они имеют только права EXEC для определенных пользовательских SP. Когда пользователям разрешено выполнять произвольные вычисления (и регулярно менять эти определения), я помещаю эту ответственность в автора отчета или помещаю формулу в пространство конфигурации, где оно интерпретируется приложением, где изменения в нем могут быть пойманный аудиторским следом. –

+0

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

0

Если производительность важна, используйте триггер или индексированный вид для хранения вычислений при вставке, обновлении или удалении данных.

Если производительность не важна, используйте функцию скалярного значения.