PostgreSQL UPDATE, похоже, не обновляет некоторые строки - PullRequest
0 голосов
/ 20 июня 2020

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

Я использую следующую инструкцию:

UPDATE lotes_infos l
SET quali_ambiental = s.quali_ambiental
FROM sirgas_lotes_centroid s
WHERE l.sql = s.sql AND l.quali_ambiental IS NULL;

Он говорит, что было обновлено 647 строк, но я не вижу изменений. Я также пробовал без предложения is null, результаты такие же.

Если я выполняю соединение, кажется, что он работает, как ожидалось, запрос соединения, который я использовал, следующий:

SELECT sql, l.quali_ambiental, c.quali_ambiental FROM lotes_infos l
JOIN sirgas_lotes_centroid c
USING (sql)
WHERE l.quali_ambiental IS NULL;

Он возвращает 787 строк (некоторые из них пустые, это нормально), это образец результата соединения:

    sql     | quali_ambiental | quali_ambiental
------------+-----------------+-----------------
 1880040001 |                 | PA 10
 1880040001 |                 | PA 10
 0863690003 |                 | PA 4
 0850840001 |                 | PA 4
 3090500003 |                 | PA 4
 1330090001 |                 | PA 10
 1201410001 |                 | PA 9
 0550620002 |                 | PA 6
 0430790001 |                 | PA 1
 1340180002 |                 | PA 9

Я использовал QGIS для визуализации результатов и не смог найти никаких подсказок, почему это происходит. sirgas_lotes_centroid берется из другой таблицы, геометрия является центроидом многоугольника. Я использовал центроид для более быстрого пространственного объединения, и теперь мне нужно поместить информацию в таблицу с исходным многоугольником.

Столбец sql имеет тип text, quali_ambiental равен varchar(6) для обоих .

Если напрямую обновить одну строку с помощью следующего запроса, он работает нормально:

UPDATE lotes_infos
SET quali_ambiental = 'PA 1'
WHERE sql LIKE '0040510001';

1 Ответ

1 голос
/ 20 июня 2020

Если вы не видите результатов, казалось бы, надежного запроса на изменение данных, первый вопрос, который нужно задать:

Вы зафиксировали свою транзакцию?

Многие клиенты работают с автоматической фиксацией по умолчанию, но некоторые нет. И даже в стандартном клиенте psql вы можете начать явную транзакцию с помощью BEGIN (или вариантов синтаксиса), чтобы отключить автоматическую фиксацию. Тогда результаты не будут видны для других транзакций до того, как транзакция будет фактически зафиксирована с помощью COMMIT. Он может зависать на неопределенное время (что создает дополнительные проблемы) или откатывается при более позднем взаимодействии.

Тем не менее, вы упоминаете: some are both null, that's ok. Вы захотите избежать дорогостоящих пустых обновлений, используя что-то вроде:

UPDATE lotes_infos l
SET    quali_ambiental = s.quali_ambiental
FROM   sirgas_lotes_centroid s
WHERE  l.sql = s.sql
AND    l.quali_ambiental IS NULL
AND    s.quali_ambiental IS NOT NULL;  --!

Связанное:

Дубликат 1880040001 в вашем примере может иметь два объяснения. Либо lotes_infos.sql не UNIQUE (даже после фильтрации с помощью l.quali_ambiental IS NULL). Или sirgas_lotes_centroid.sql не UNIQUE. Или оба.

Если это просто lotes_infos.sql, ваш запрос все равно должен работать. Но дубликаты в sirgas_lotes_centroid.sql делают запрос недетерминированным c (как также указал @jjanes). Целевая строка в lotes_infos может иметь несколько кандидатов в sirgas_lotes_centroid. Результат произвольный из-за отсутствия определения. Если в одном из них указано quali_ambiental IS NULL, это может объяснить то, что вы наблюдали.

Предлагаемый мной запрос устраняет наблюдаемую проблему поверхностно, поскольку исключает значения NULL из исходной таблицы. Но если для одного и того же sirgas_lotes_centroid.sql может быть несколько отличных от NULL, различных quali_ambiental, ваш запрос останется неработающим, так как результат будет произвольным. Вам нужно будет определить, какую исходную строку выбрать и преобразовать в SQL.

Вот один пример того, как это сделать (глава «Множественные совпадения ...»):

Всегда включать точные определения таблиц (CREATE TABLE утверждения) с любым таким вопросом. Это сэкономит много времени, потраченного на спекуляции.

Кроме того: почему столбцы sql имеют тип text? Такие значения, как 1880040001, кажутся мне integer или bigint. В таком случае text - это дорогостоящая ошибка проектирования.

...