小提琴链接:https ://dbfiddle.uk/EOE627Oa
表
CREATE TABLE accounts (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
login text NOT NULL,
password text NOT NULL,
email text,
init_index bigint,
parent_id bigint REFERENCES accounts
);
输入数据
[
{
"login": "11EB19631A",
"password": "AE128AADEF97F1E54021",
"reference_id": 1
},
{
"login": "3ED4ECBBC9",
"password": "E67EDDB6033D02140BB4",
"email": "a@b",
"reference_id": 2,
"parent_reference": 1
},
{
"login": "C86D7E2CF0",
"password": "75404617C000A0EB070C",
"reference_id": 3,
"parent_reference": 2
},
{
"login": "C51D77BF87",
"password": "605509993A05EE393081",
"email": null,
"reference_id": 4,
"parent_reference": 2
},
{
"login": "2BAB5AA533",
"password": "DFCAB818D812B1F8F761",
"reference_id": 5,
"parent_reference": 3
},
{
"login": "4229D47E2C",
"password": "CE4E14ED6AD77CBC71B5",
"email": "b@c",
"reference_id": 6,
"parent_reference": 2
}
]
询问
WITH account_inits AS (
SELECT
row_number () OVER () as init_index,
login,
password,
email,
reference_id,
parent_reference
FROM
json_to_recordset(
$json$$json$
) AS input_init(
login text,
password text,
email text,
reference_id int,
parent_reference int
)
),
-- create new accounts
new_accounts AS (
INSERT INTO accounts
(
init_index,
login,
password,
email
)
SELECT
init_index,
login,
password,
email
FROM
account_inits
RETURNING
*
),
parent_id_pairs AS (
SELECT
new_accounts.id,
account_inits.reference_id
FROM
new_accounts
INNER JOIN
account_inits
ON
account_inits.reference_id IN (
SELECT DISTINCT
parent_reference AS reference_id
FROM
account_inits
)
AND
new_accounts.init_index = account_inits.init_index
),
account_updates AS (
SELECT
new_accounts.id,
parent_id_pairs.id AS parent_id
FROM
new_accounts
INNER JOIN
account_inits
ON
account_inits.parent_reference IS NOT NULL
AND
new_accounts.init_index = account_inits.init_index
INNER JOIN
parent_id_pairs
ON
account_inits.parent_reference = parent_id_pairs.reference_id
),
updated_accounts AS (
UPDATE
accounts
SET
parent_id = account_updates.parent_id
FROM
account_updates
WHERE
account_updates.id = accounts.id
RETURNING
*
)
SELECT
*
FROM
updated_accounts
;
SELECT
id,
init_index,
parent_id
FROM
accounts
;
问题
有问题的表有一个外键来表达其行之间的树状关系。但是这些关系甚至在批量插入之前就可以知道。因此reference_id
和parent_reference
是由应用程序生成的“批处理标识符”,用于显示初始化程序之间的引用。
INSERT
然而,由于显而易见的原因,数据库不能在语句中表达这种关系。所以我考虑UPDATE
在 CTE 中为新创建的行运行一个单独的步骤。但它不起作用,尽管所有输入数据都是正确的(您可以通过SELECT
'ing CTE 中使用的UPDATE
CTE 来检查),所以问题出在UPDATE
块本身。文档列出UPDATE
了从一组记录中执行的两种不同语法。我尝试了它们,但都没有将它们应用于parent_id
创建的行。