Как обрабатывать нулевое значение в подготовленном операторе sqlite

#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 and IS 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) может помочь запросу.