PostgreSQL: подзапрос возвращает более одной строки - PullRequest
0 голосов
/ 20 сентября 2018

Может кто-нибудь, пожалуйста, помогите мне?Я уже несколько раз проверял свой SQL-код и не могу понять, почему время от времени возникает ошибка.В каждом подзапросе существует жесткое ограничение LIMIT 1, как такой подзапрос может возвращать более одной строки?

Эта проблема может быть воспроизведена при выполнении этого запроса в двух параллельных соединениях.

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

            WITH update_current(number) AS (
                UPDATE numeric_pool
                SET updating_field = updating_field + 1,
                    date_modified = NOW()
                WHERE numeric_pool_id = (
                    SELECT numeric_pool_id
                    FROM numeric_pool
                    WHERE condition_field1 = 58
                    AND condition_field2 = 4
                    AND date_modified < NOW() - INTERVAL '150 s'
                    AND updating_field < 1
                    ORDER BY numeric_pool_id
                    LIMIT 1
                )
                RETURNING number
            ), insert_new(number) AS (
                WITH pool(number) AS (
                    VALUES (100), (200)
                )
                INSERT INTO numeric_pool (number, condition_field1, condition_field2, updating_field, date_modified)
                SELECT * FROM (
                    SELECT p.number, 58, 4, 1, NOW()
                    FROM pool p
                    LEFT JOIN numeric_pool dp ON (
                        p.number = dp.number
                        AND dp.condition_field1 = 58
                        AND dp.condition_field2 = 4
                    )
                    WHERE dp.numeric_pool_id IS NULL
                    LIMIT 1
                ) subquery
                WHERE NOT EXISTS(SELECT * FROM update_current)
                RETURNING number
            ), update_old(number) AS (
                UPDATE numeric_pool
                SET updating_field = 1,
                    date_modified = NOW()
                WHERE NOT EXISTS(SELECT * FROM update_current)
                AND NOT EXISTS(SELECT * FROM insert_new)
                AND numeric_pool_id = (
                    SELECT numeric_pool_id
                    FROM numeric_pool
                    WHERE condition_field1 = 58
                    AND condition_field2 = 4
                    AND date_modified < NOW() - INTERVAL '0 s'
                    ORDER BY date_modified
                    LIMIT 1
                )
                RETURNING number
            )
            SELECT COALESCE(
                (SELECT * FROM update_current),
                (SELECT * FROM insert_new),
                (SELECT * FROM update_old)
            ) AS number

Я заменил последнюю часть запроса, отказавшись использовать COALESCE, затем ошибка исчезла из базы данных.журналы.Поэтому один из подзапросов COALESCE возвратил более одной строки, вероятно, последний подзапрос, поскольку первые два подзапроса не должны возвращать значения в моих данных.Однако этот подзапрос имеет значение UPDATE для первичного ключа, он не может возвращать более одной строки?

                SELECT number FROM (
                    SELECT * FROM update_current
                    UNION SELECT * FROM insert_new
                    UNION SELECT * FROM update_old
                ) finquery
                LIMIT 1

Вот моя таблица:

CREATE TABLE numeric_pool
(
  numeric_pool_id serial NOT NULL, -- Primary key
  condition_field1 integer NOT NULL,
  "number" bigint NOT NULL,
  condition_field2 integer NOT NULL,
  updating_field integer NOT NULL,
  date_modified timestamp without time zone NOT NULL,
  CONSTRAINT numeric_pool_pkey PRIMARY KEY (numeric_pool_id)
)
WITH (
  OIDS=FALSE
);

Этот запрос в моем приложении выполняется параллельно.

PostgreSQL 9.6.0 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit

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