-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Delete dependents that does not have a primary key #17
Comments
Hey, @aelgn. Thanks for the comment. Be first advised that I haven't had the opportunity to work with PG in almost two years (and don't even have a local install ATM). My time isn't really my own anymore :/ BUT... a couple questions: What's your PG version? And what's your situation? You've got an FK pointing at a unique key and not a PK? |
Hi @trlorenz - no worries, I know the feeling :)
recursive_delete('A') fails since fk relations in C are not deleted. I'm guessing it is because C does not have a declared PK. |
Understood, and you're correct -- it's because C has no PK. Tables involved in the recursive deletion query are strung together by their foreign keys and the primary/unique keys that they reference. In your example, table B isn't important. Let's look at the situation with tables A and C, but let's give C a primary key: DROP TABLE IF EXISTS c;
DROP TABLE IF EXISTS a;
CREATE TABLE a (id SERIAL PRIMARY KEY);
-- CREATE TABLE c (a_id int4 NULL REFERENCES a);
CREATE TABLE c (id SERIAL PRIMARY KEY, a_id int4 NULL REFERENCES a);
INSERT INTO a VALUES (99);
INSERT INTO c (a_id) VALUES (99);
SELECT recursively_delete('A', 99); As expected, that works:
Here's the recursive query itself: WITH
"del_0$ROOT" AS (
DELETE FROM a WHERE (id) IN (
WITH RECURSIVE
self_ref (id) AS (
SELECT id FROM a WHERE (id) IN (99)
UNION ALL
SELECT NULL
)
SELECT id FROM self_ref
) RETURNING *
)
,
"del_1$13320130" AS (
DELETE FROM c WHERE (id) IN (
WITH RECURSIVE
self_ref (id) AS (
SELECT id FROM c WHERE (a_id) IN (SELECT id FROM "del_0$ROOT")
UNION ALL
SELECT NULL
)
SELECT id FROM self_ref
) RETURNING *
)
SELECT '0' AS queue_i, count(*) AS n_del FROM "del_0$ROOT" UNION ALL SELECT '1' AS queue_i, count(*) AS n_del FROM "del_1$13320130" Notice that each auxiliary query begins by saying, 'DELETE FROM <TABLE> WHERE <KEY_COLS> IN (...)...'. That's the lynchpin of the whole thing as currently written, relating childrens' FK's to parents' PK's to arbitrary depth. So far, I can think of two possible ways to address your issue, but both would involve pretty substantial rewrites. It's an interesting problem, and now that you've put it in my head, my OCD will force me to think about it. (Damn you!) But I can't promise an implemented solution real soon. I have to ask: Can you throw a PK on that table? If this deletion you're doing is a one-off, you could even drop it after you were done. Or maybe (a_id, b_id) is unique and deserves permanent PK status anyway. |
Ah yes I see now, thank you for the writeup. I did add identity pk on the problematic binding tables and was able to recursively delete 馃憤 |
Very nice procedure 馃憤
However, after testing it for my use case I realized that it will ignore dependant tables that themselves does not declare a primary key. Thus, they are not deleted and the transaction rolls back due to fk constraint violation.
Would be really nice to be able to delete dependants without their own pk.
The text was updated successfully, but these errors were encountered: