Sqlite3: Какое правильное слово mojo для слова «удалить ... где не в ...?» - PullRequest
0 голосов
/ 09 мая 2019

Я просто пытаюсь удалить все строки в одной таблице, у которых нет соответствующей строки в другой таблице. Примерно так:

DELETE FROM table1 WHERE table1.pk NOT IN (SELECT fk FROM table2);

Но я должен делать что-то глупое. Запрос SELECT - найти строки, которые я хочу удалить - кажется достаточно простым (и выдает правильные ответы), , но я просто не получаю нигде с DELETE. Либо он вообще не работает, либо удаляет неправильные вещи.

(Запросы, которые я имею в виду, прекрасно работают на других СУБД, но я знаю, что поддержка SQLite более ограничена. И да, я действительно знаком с тем, как работает SQL ... не первый родео.)

Некоторые люди предлагали что-то сделать с NOT EXISTS, но я уверен, что добрые люди просто ответили бы «запросом, который работает». Мой лоб поблагодарит тебя ...

Ответы [ 3 ]

0 голосов
/ 10 мая 2019

К вашему сведению ... вот точный SQL-запрос, который работал:

delete from wagtailcore_pagerevision 
  where id in (select r.id from wagtailcore_pagerevision r 
    left join wagtailcore_page p on r.id=p.live_revision_id 
    where p.live_revision_id is null);

Как видите, "довольно стандартные LEFT JOIN вещи."

«Еще раз спасибо, StackOverflow!» ... Еще не совсем уверен, где сегодня был припаркован мой «LEFT мозг» ... (ну, пора пива) ... : - D

0 голосов
/ 10 мая 2019

Ну, единственный случай, когда этот код:

DELETE FROM wagtailcore_pagerevision 
WHERE id NOT IN (SELECT live_revision_id FROM wagtailcore_page);

не будет работать, это если в столбце live_revision_id в таблице wagtailcore_page есть значения null.Поскольку, если есть нулевые значения, они включаются в результат подзапроса:

SELECT live_revision_id FROM wagtailcore_page

, поэтому для каждого id из wagtailcore_pagerevision, не существующего в результатах подзапроса, это:

IN (SELECT live_revision_id FROM wagtailcore_page)

возвращает null, поскольку оно сравнивается (также) с null, а NOT IN наконец возвращает null, что означает неизвестный или неопределенный , какой изКонечно, не TRUE.Из Функции и операторы сравнения (для MySQL, но это относится и к SQLite, так как это стандарт SQL):

Чтобы соответствовать стандарту SQL, IN возвращает NULL не только есливыражение в левой части равно NULL, но также если совпадение не найдено в списке и одно из выражений в списке равно NULL.

См. демо .Таким образом, решение вашей проблемы было бы:

DELETE FROM wagtailcore_pagerevision 
WHERE id NOT IN (
  SELECT live_revision_id 
  FROM wagtailcore_page 
  WHERE live_revision_id IS NOT NULL
);

См. demo .

0 голосов
/ 09 мая 2019

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

Пример:

$ sqlite3
SQLite version 3.28.0 2019-04-16 19:49:53
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> create table table1(id integer);
sqlite> insert into table1 values (1),(2),(3),(4),(5);
sqlite> create table table2(id2 integer);
sqlite> insert into table2 values (1),(3),(5);
sqlite> select * from table1 where id not in (select id2 from table2);
id
----------
2
4
sqlite> delete from table1 where id not in (select id2 from table2);
sqlite> select * from table1;
id
----------
1
3
5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...