SQLite inner join-обновление с использованием значений из другой таблицы
Это довольно легко и был задан несколько раз, но я не могу заставить его работать. SQL-запрос, который я думаю, должен работать:
UPDATE table2
SET dst.a = dst.a + src.a,
dst.b = dst.b + src.b,
dst.c = dst.c + src.c,
dst.d = dst.d + src.d,
dst.e = dst.e + src.e
FROM table2 AS dst
INNER JOIN table1 AS src
ON dst.f = src.f
5 ответов
использование инструкции update невозможно, поскольку в SQLite соединения в инструкции update не поддерживаются. См Docs: инструкции Update
Если вы хотите обновить только один столбец до статического значения, вы можете правильно использовать подзапрос в инструкции update. См. этот пример:как сделать обновление при объединении таблиц на SQLite?
теперь в вашем примере, делая предположение, что есть уникальный ключ на " столбец f" - обходной путь / решение, которое я придумал, использует оператор replace:
replace into table2
(a, b, c, d, e, f, g)
select src.a, src.b, src.c, src.d, src.e, dest.f, dest.g
from table1 src
inner join table2 dest on src.f = dest.f
Я также добавил дополнительный столбец в table2 "столбец g", чтобы показать, как вы" обновите " только некоторые столбцы с помощью этого метода.
еще одна вещь, о которой нужно быть осторожным, - это если вы используете "PRAGMA foreign_keys = ON;" можно иметь проблемы с этим, поскольку строка эффективно удаляется и вставляется.
я придумал альтернативную технику с использованием триггера и" реверсирования " направления обновления, хотя и за счет фиктивного поля в исходной таблице.
в общих чертах, у вас есть Master
и Updates
таблица. Вы хотите обновить несколько полей в Master
из соответствующих полей Updates
связанный ключевым полем Key
.
вместо UPDATE Master SET ... FROM Master INNER JOIN Updates ON Mater.Key = Updates.Key
выполнить следующее:
добавить манекен поле
TriggerField
доUpdates
таблица, чтобы действовать в качестве фокуса триггера.-
создайте триггер в этом поле:
CREATE TRIGGER UpdateTrigger AFTER UPDATE OF TriggerField ON Updates BEGIN UPDATE Master SET Field1 = OLD.Field1, Field2 = OLD.Field2, ... WHERE Master.Key = OLD.Key END;
-
запустите процесс обновления следующим образом:
UPDATE Updates SET TriggerField = NULL ;
Примечания
фиктивное поле-это просто якорь для триггера, так что любой другой
UPDATE Updates SET ...
не будет запускать обновление вMaster
. Если вы только когда-нибудьINSERT
наUpdates
затем вы не нужно (и может удалитьOF TriggerField
предложение при создании триггера).из некоторых грубых и готовых таймингов это, похоже, работает примерно с той же скоростью, что и
REPLACE INTO
но избегает по ощущениям-чуть-не так техника удаления и добавления строк. Это также проще, если вы обновляете только несколько полей вMaster
как вы только список тех, которые вы хотите изменить.-
это на порядки быстрее, чем другие альтернатива, которую я видел
UPDATE ... FROM
что:UPDATE Master SET Field1 = ( SELECT Field1 FROM Updates WHERE Mater.Key = Updates.Key ), Field1 = ( SELECT Field1 FROM Updates WHERE Mater.Key = Updates.Key ), ... ;
обновление шести полей более 1700 записей было примерно 0.05 s для Тони и моих методов, но 2.50 s на
UPDATE ... ( SELECT... )
метод. AFTER UPDATE
триггерыMaster
кажется, огонь, как и ожидалось.
Как говорит Тони, решением является заменить на путь, но вы можете использовать скрытое поле sqlite rowid для имитации полного обновления с помощью join like:
replace into table2
(rowid,a, b, c, d, e, f, g)
select dest.rowid,src.a, src.b, src.c, src.d, src.e, dest.f, dest.g
from table1 src
inner join table2 dest on src.f = dest.f
С этим вы воссоздаете полные строки, Если у вас нет первичного ключа для замены или стандартного метода для обновления с помощью соединений.
SQLITE не поддерживает обновление с внутренним соединением, а также несколько других БД. Внутренние соединения хороши и просты, однако это может быть достигнуто с помощью только обновления и выбора подзапроса. Используя предложение where и " IN "с подзапросом и дополнительным подзапросом для "SET", всегда можно достичь одного и того же результата. Ниже показано, как это делается.
UPDATE table2
SET a = a + (select a from table1 where table1.f = table2.f),
b = b + (select b from table1 where table1.f = table2.f),
c = c + (select c from table1 where table1.f = table2.f),
d = d + (select d from table1 where table1.f = table2.f),
e = e + (select e from table1 where table1.f = table2.f)
WHERE RowId IN (Select table2.RowId from table1 where table1.f = table2.f)
использовать ниже запроса:
UPDATE table2
SET a = Z.a,
b = Z.b,
c = Z.c,
d = Z.d,
e = Z.e
FROM (SELECT dst.id,
dst.a + src.a AS a,
dst.b + src.b AS b,
dst.c + src.c AS c,
dst.d + src.d AS d,
dst.e + src.e AS e
FROM table2 AS dst
INNER JOIN table1 AS src ON dst.f = src.f
)Z
WHERE table2.id = z.id