#c #c #sqlite #where-clause #sql-null
#c #c #sqlite #where-предложение #sql-null
Вопрос:
Рассмотрим базу данных, которая моделирует дерево каталогов, и каждый файл или папка является записью:
CREATE TABLE "tree" (
"id" integer,
"parent_id" integer,
"name" varchar(255),
UNIQUE("parent_id","name"),
PRIMARY KEY("id"),
FOREIGN KEY("parent_id") REFERENCES "tree"("id") on delete cascade
);
Для корневого узла parent_id установлено значение NULL, поскольку у него нет родительского элемента.
Чтобы оптимизировать время выполнения, я хочу создать подготовленный оператор для запроса дерева:
select * from tree where name=? and parent_id=?
Проблема в том, что с помощью приведенного выше оператора, даже если я вызову sqlite3_bind_null, оператор select не найдет строки с parent_id NULL . Он работает только с аргументом parent_id is null
.
В настоящее время подготовлены два оператора: один для NULL и один для != NULL, но это не очень элегантно. Есть ли другой способ добиться этого?
Ответ №1:
Вы хотите null
-безопасное равенство. В SQLite вы можете использовать is
:
select *
from tree
where name = ? and parent_id is ?
Как это работает, объясняется в документации:
Операторы
IS
andIS NOT
работают так же, как=
и!=
, за исключением случаев, когда один или оба операнда являютсяNULL
. В этом случае, если оба операнда равныNULL
, тоIS
оператор принимает значение 1 (true), аIS NOT
оператор принимает значение 0 (false). Если один операндNULL
равен, а другой нет, тоIS
оператор принимает значение 0 (false), аIS NOT
оператор равен 1 (true).
Комментарии:
1. Действительно, это работает! Но, к сожалению, сейчас это примерно в 2,5 раза медленнее. (кстати. Я не понизил голос, я нахожу это полезным).
2. @MiB_Coder: Я думаю, это цена, которую нужно заплатить за функцию защиты от нуля… Индекс в
(name, parent_id)
or (parent_id, name)
может помочь запросу.