Я считаю, что это безопасно, независимо от того, в каком порядке выполняются CTE. Я думаю, что мне удалось заставить их работать не по порядку, и я не увидел никаких ошибок FK.
У меня фактически есть две родительские таблицы и запрос, который больше похож на
WITH tmp (parent1_id, parent2_id, child_id, parents_val, child_val) AS (
VALUES (...)
),
ins_parent1 AS (
INSERT INTO parent1 (parent1_id, parents_val)
SELECT DISTINCT parent1_id, parents_val FROM tmp
)
ins_parent2 AS (
INSERT INTO parent2 (parent2_id, parents_val)
SELECT DISTINCT parent2_id, parents_val FROM tmp
)
INSERT INTO child (child_id, parent1_id, parent2_id, child_val)
SELECT child_id, parent1_id, parent2_id, child_val FROM tmp
Когда я проверяю план выполнения (EXPLAIN WITH tmp ...
), он выглядит примерно так:
Insert on child
CTE tmp
-> ...
CTE ins_parent1
-> ...
CTE ins_parent2
-> ...
-> ...
, что, я думаю, означает, что все три CTE будут выполнены перед вставкой в child
.
Но я могу изменить порядок запроса, чтобы поместить child
в CTE, а parent1
снаружи:
WITH tmp (parent1_id, parent2_id, child_id, parents_val, child_val) AS (
VALUES (...)
),
ins_child AS (
INSERT INTO child (child_id, parent1_id, parent2_id, child_val)
SELECT child_id, parent1_id, parent2_id, child_val FROM tmp
)
ins_parent2 AS (
INSERT INTO parent2 (parent2_id, parents_val)
SELECT DISTINCT parent2_id, parents_val FROM tmp
)
INSERT INTO parent1 (parent1_id, parents_val)
SELECT DISTINCT parent1_id, parents_val FROM tmp
и план выполнения изменяется соответственно:
Insert on parent1
CTE tmp
-> ...
CTE ins_child
-> ...
CTE ins_parent2
-> ...
-> ...
так что теперь я думаю, что CTE для child
выполняется до того, как что-либо будет вставлено в parent1
.
Но я все еще не получаю ошибок FK с таким запросом, который заставляет меня думать, что любой порядок выполнения безопасен.