Now for the insert: Test data: watch_list_id = 3724 user_id = 1 This is the original design: insert into watch_list_element (watch_list_id, element_id) values (3724, 633); Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.02..0.02 rows=1 loops=1) Total runtime: 1.46 msec This will verify that the user does own this watch list: SELECT id FROM watch_list WHERE user_id = 1 AND id = 3724; - one row found Index Scan using watch_list_pkey on watch_list (cost=0.00..5.33 rows=1 width=4) (actual time=0.28..0.30 rows=1 loops=1) Total runtime: 0.43 msec - not found Index Scan using watch_list_pkey on watch_list (cost=0.00..5.33 rows=1 width=4) (actual time=0.32..0.32 rows=0 loops=1) Total runtime: 0.44 msec This will do the insert: insert into watch_list_element (watch_list_id, element_id) values ( (SELECT id FROM watch_list WHERE user_id = 1 AND id = 3724), 633); - one row to insert Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.34..0.34 rows=1 loops=1) InitPlan -> Index Scan using watch_list_pkey on watch_list (cost=0.00..5.33 rows=1 width=4) (actual time=0.28..0.29 rows=1 loops=1) Total runtime: 1.00 msec - nothing to insert ERROR: ExecAppend: Fail to add null value in not null attribute watch_list_id Which is fine.