Принудительная Параметризация
реляционные выражения, содержащие NULL, на самом деле снова возвращают NULL
edit
здесь <>
обозначает произвольный бинарный оператор, NULL
- Заполнитель SQL, а значение
- любое значение ( NULL
равно не значение):
NULL <> значение
-> NULL
NULL <> NULL
-> NULL
логика следующая: NULL
означает «нет значения» или «неизвестное значение», и, следовательно, любое сравнение с любым фактическим ] значение не имеет смысла.
равно X = 42
истина, ложь или неизвестно, если вы не знаете, какое значение (если любое ) X
держится? SQL говорит, что это неизвестно. X = Y
истина, ложь или неизвестно, учитывая, что оба неизвестны? SQL сообщает, что результатом является неизвестно . и это говорит об этом для любой бинарной реляционной операции, которая является только логической (даже если наличие NULL в модели не в первую очередь).
SQL также предоставляет два унарных постфиксных оператора, IS NULL
и IS NOT NULL
, они возвращают TRUE или FALSE в соответствии с их операндом.
NULL IS NULL
-> TRUE
NULL IS NOT NULL
-> FALSE
Потому что такое поведение следует установленной тернарной логике , где NULL считается неизвестным значением.
Если вы думаете о NULL как о неизвестном, оно становится более интуитивным:
] неизвестно a
равно неизвестно b
? Невозможно узнать, поэтому: неизвестно
.
Все сравнения, включающие null
, не определены и оцениваются к ложному. Эта идея, которая предотвращает оценку null
как эквивалент null
, также предотвращает оценку null
как НЕ эквивалентную null
.
Короткий ответ ... NULL странные , они действительно не ведут себя так, как вы ожидаете.
Вот отличная статья о том, как работают NULL. в SQL. Я думаю, это поможет вам лучше понять тему. Я думаю, что разделы по обработке нулевых значений в выражениях будут для вас особенно полезны.
http://www.oracle.com/technology/oramag/oracle/05-jul/o45sql.html
Если у вас есть иерархия исключений, throw ex
может вырезать ваше исключение, а throw
- нет. Например:
#include <iostream>
#include <string>
using namespace std;
struct base
{
virtual string who() {return "base";}
};
struct derived : public base
{
string who() {return "derived";}
};
int main() {
try {
try {
throw derived(); // throws a 'derived'
}
catch (base& ex)
{
throw ex; // slices 'derived' object to be a 'base' object
}
}
catch (base& ex)
{
cout<<ex.who()<<endl; // prints 'base'
}
}
Измените throw ex
на просто throw
, и вы получите результат производный
, который вы, вероятно, ожидали получить.
SET ANSI_NULLS OFF
select result =
case
when null=null then 'eq'
else 'ne'
end
SET ANSI_NULLS ON
select result =
case
when null=null then 'eq'
else 'ne'
end
«Неизвестно a равно неизвестному b? Нет никакого способа узнать, поэтому: unknown.»
Возник вопрос: почему сравнение дает FALSE?
Учитывая три- оцененная логика, было бы разумно, если бы сравнение дало НЕИЗВЕСТНО (не ЛОЖЬ). Но SQL действительно возвращает ЛОЖЬ, а не НЕИЗВЕСТНО.
Одна из бесчисленных извращений в языке SQL.
Кроме того, необходимо принять во внимание следующее:
Если «неизвестно» является логическим значением в троичной системе. логика, то должно быть так, что сравнение на равенство между двумя логическими значениями, которые оба являются (значением) "неизвестным", тогда это сравнение должно дать ИСТИНА.
Если логическое значение само по себе неизвестно, тогда очевидно, что это не может быть представлено, помещая туда значение "unknown", потому что это означало бы, что логическое значение известно (как «неизвестно»). То есть, как реляционная теория доказывает, что реализация 3-значной логики поднимает требование для 4-значной логики, что 4-значная логика приводит к необходимости 5-значной логики и т. Д. И т. Д. До бесконечности.