有人可以帮助我吗? 我已经检查过几次我的SQL代码,并且不明白为什么有时会发生错误。在每个子查询中,对LIMIT 1都有硬性限制,这样的子查询如何返回多行呢?
可以通过在两个并行连接中运行此查询来重现此问题。
numerical_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