Обработка значений ошибок в стандарте SQL - PullRequest
1 голос
/ 17 июля 2009

У меня есть вопрос о стандарте SQL, который, я надеюсь, поможет юристу по языку SQL .

Некоторые выражения просто не работают. 62 / 0, например. Стандарт SQL определяет несколько способов, с помощью которых выражения могут ошибаться подобными способами. Многие языки работают с этими выражениями, используя специальное исключительное управление потоком или bottom psuedo-values.

У меня есть таблица, t, с (только) двумя столбцами, x и y каждого типа int. Я подозреваю, что это не актуально, но для определенности предположим, что (x,y) является первичным ключом t. Эта таблица содержит (только) следующие значения:

x    y
7    2
3    0
4    1
26   5
31   0
9    3

Какое поведение требуется стандартом SQL для выражений SELECT, работающих с этой таблицей, которые могут включать деление (я) на ноль? В качестве альтернативы, если ни одно поведение не требуется, какое поведение разрешено?

Например, какое поведение требуется для следующих операторов выбора?

Самый простой:

SELECT x, y, x / y AS quot
FROM t

Сложнее:

SELECT x, y, x / y AS quot
FROM t
WHERE y != 0

Еще сложнее:

SELECT x, y, x / y AS quot
FROM t
WHERE x % 2 = 0

Было бы разрешено, чтобы реализация (скажем, та, которая не смогла понять в более сложной версии этого запроса, что ограничение может быть перемещено внутри расширения) могла произвести ошибку деления на ноль в ответ на этот запрос, потому что, скажем, он попытался разделить 3 на 0 как часть расширения, прежде чем выполнить ограничение и понять, что 3 % 2 = 1? Это могло бы стать важным, если, например, расширение было над маленькой таблицей, но результат - когда он был объединен с большой таблицей и ограничен на основе данных в большой таблице - в конечном итоге ограничил все строки, которые требуется деление на ноль.

Если бы t имел миллионы строк, и этот последний запрос выполнялся при сканировании таблицы, была бы разрешена реализация, чтобы вернуть первые несколько миллионов результатов до обнаружения деления на ноль в конце при обнаружении одного четного значения x с нулевое значение у? Требуется ли буферизация?

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

SELECT x, y
FROM t
WHERE ((x / y) >= 2) AND ((x % 2) = 0)

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

SELECT CASE 
       WHEN EXISTS 
            (
                SELECT x, y, x / y AS quot
                FROM t
            )
       THEN 1
       ELSE 0
       END AS what_is_my_value

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

Я был бы признателен за руководство, потому что не могу найти соответствующую часть (и) спецификации.

1 Ответ

1 голос
/ 17 июля 2009

Все реализации SQL, с которыми я работал, рассматривают деление на 0 как непосредственное NaN или #INF. Предполагается, что разделение будет обрабатываться внешним интерфейсом, а не самой реализацией. Запрос не должен заканчиваться, но в этом случае набор результатов должен возвращать NaN. Поэтому он возвращается в то же время, что и набор результатов, и пользователю не выдается никакого специального предупреждения или сообщения.

В любом случае, чтобы правильно с этим справиться, используйте следующий запрос:

select
   x, y, 
   case y 
       when 0 then null 
       else x / y 
   end as quot
from
   t

Чтобы ответить на ваш последний вопрос, это утверждение:

SELECT x, y, x / y AS quot
FROM t

Вернет это:

x    y   quot
7    2    3.5
3    0    NaN
4    1      4
26   5    5.2
31   0    NaN
9    3      3

Итак, ваш exists найдет все строки в t, независимо от их отношения.

Кроме того, я снова перечитал ваш вопрос и понял, что не обсуждал предложения where (к стыду!). Предложение where, или predicate, должно всегда применяться до вычисления столбцов.

Подумайте над этим запросом:

select x, y, x/y as quot from t where x%2 = 0

Если у нас была запись (3,0), применяется условие where и проверяется, если 3 % 2 = 0. Это не так, поэтому она не включает эту запись в вычисления столбцов и оставляет ее там, где она есть.

...