Вставка строк в таблицу с использованием условия WHERE и JOIN из другой таблицы в SQLite - PullRequest
0 голосов
/ 29 мая 2019

У меня есть две таблицы (скажем, таблица 1 и таблица 2), и у меня есть 8 столбцов в каждой таблице (v_id, p_id, cat, s1, s2, s3, s4, s5, s6, u_name, P_date)

Я хочу вставить значения в таблицу1 из таблицы2 со следующими условиями:

  1. если v_id уже существует в таблице 1, а p_id в таблице 2 совпадает с таблицей 1, он должен заменить v_id в таблице 1 на v_id в таблице 2
  2. если v_id не существует в таблице 1, он просто должен добавить эти v_ids в таблицу 1
  3. если v_id существует, но p_id в таблице 2 не совпадает с таблицей 1, он должен добавить v_ids к таблице 1

Пока я пробовал:

Я инициировал таблицы следующим образом:

CREATE TABLE IF NOT EXISTS table1(v_id, cat TEXT, s1 TEXT,s2 TEXT,s3 TEXT, s4 TEXT,s5 TEXT,s6 TEXT, u_name TEXT, p_date DATE, p_id TEXT)

CREATE TABLE IF NOT EXISTS table2(v_id, cat TEXT, s1 TEXT,s2 TEXT,s3 TEXT, s4 TEXT,s5 TEXT,s6 TEXT, u_name TEXT, p_date DATE, p_id TEXT)

Я вставил некоторые данные в таблицу 1 и таблицу 2 и попробовал следующий код:

INSERT OR REPLACE INTO table1 SELECT * FROM table2
LEFT JOIN table1 ON table2.v_id=table1.v_id
WHERE table2.p_id=table1.p_id OR table1.v_id IS NULL

Но мне выдается следующая ошибка:

"table table1 has 11 columns but 22 values were supplied"

что я делаю не так ??

1 Ответ

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

Это SELECT * возвращает 22 столбца. Зачем? Потому что он возвращает столбцы из JOIN, а не только из table2. Из sqlite ВЫБРАТЬ документ :

Если оператор соединения представляет собой «LEFT JOIN» или «LEFT OUTER JOIN», то после применяются условия фильтрации ON или USING, дополнительная строка добавляется к выходу для каждой строки в исходном вводе слева набор данных, который соответствует отсутствию строк в составном наборе данных (если есть). Добавленные строки содержат значения NULL в столбцах, которые обычно содержат значения, скопированные из правого набора данных ввода.

SELECT table2.* from ..... исправит эту проблему .

Давайте на минутку забудем о INSERT и оценим, какие строки будут возвращены

SELECT * FROM table2
LEFT JOIN table1 ON table2.v_id=table1.v_id
WHERE table2.p_id=table1.p_id OR table1.v_id IS NULL

Он не будет выбирать строки, где table2.v_id = table1.v_id AND table2.p_id != table1.p_id, поэтому условие 3 никогда не будет выполнено.

Если table1 не имеет ограничения UNIQUE или PRIMARY KEY, замена никогда не произойдет, поэтому условие 1 никогда не будет выполнено (оно просто вставит строки из table2). Из sqlite ON CONFLICT doc:

REPLACE

Когда происходит нарушение ограничения UNIQUE или PRIMARY KEY, алгоритм REPLACE удаляет ранее существующие строки, которые вызывают нарушение ограничения перед вставкой или обновлением текущей строки и команда продолжает выполняться нормально. Если ограничение NOT NULL нарушение происходит, ЗАМЕНА разрешения конфликта заменяет NULL значение со значением по умолчанию для этого столбца, или если столбец не имеет значение по умолчанию, то используется алгоритм ABORT. Если ограничение CHECK нарушение происходит, алгоритм разрешения конфликтов ЗАМЕНА всегда работает как ABORT.

Вам нужно будет создать индекс (ы) для table1, чтобы использовать действие REPLACE. Возможно, составной индекс для v_id, p_id поможет. Что-то вроде CREATE UNIQUE INDEX "vid_pid_idx" on table1 (v_id,p_id). Затем просто INSERT OR REPLACE INTO table1 SELECT * FROM table2 для достижения целей.

Строки, в которых v_ids и p_ids равны, будут «ЗАМЕНИТЬ», потому что УНИКАЛЬНОЕ ограничение будет «нарушено».
Все остальные строки из таблицы2 будут вставлены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...