After clarifying comments, you seem to need only to store the primary key in the various verification tables. (You don't have to use an artificial or surrogate key. If "claim_num" is a natural key, and it's varchar(15), use "claim_num".)
create table Claims (
claim_id integer primary key,
other_columns_go_here char(1) not null default 'x'
);
create table EmailVerifications (
claim_id integer primary key references Claims (claim_id),
email_verification_num integer not null unique,
other_columns_go_here char(1) not null default 'x'
);
create table MetaCodes (
claim_id integer primary key references Claims (claim_id),
metacode_num integer not null unique,
other_columns_go_here char(1) not null default 'x'
);
create table CertificateFiles (
claim_id integer primary key references Claims (claim_id),
certificate_file_num integer not null unique,
other_columns_go_here char(1) not null default 'x'
);
These inserts will succeed.
insert into Claims values (20);
insert into EmailVerifications values (20, 12);
insert into CertificateFiles values (20, 124);
The first two inserts will succeed. The PRIMARY KEY constraint on "EmailVerifications" will make the third one will fail.
insert into Claims values (43);
insert into EmailVerifications values (43, 1034);
insert into EmailVerifications values (43, 450);
The following doesn't match the clarified requirements. Consider its continued presence a bonus.
If I understand correctly, you want each row in Claims to be referenced by either zero rows, or by one and only one row.
create table Claims (
claim_id integer primary key,
verification_code char(1) not null
check (verification_code in ('c', 'e', 'm')),
unique (claim_id, verification_code),
other_columns_go_here char(1) not null default 'x'
);
create table EmailVerifications (
claim_id integer not null,
verification_code char(1) not null default 'e'
check (verification_code = 'e'),
primary key (claim_id, verification_code),
foreign key (claim_id, verification_code)
references Claims (claim_id, verification_code),
other_columns_go_here char(1) not null default 'x'
);
create table MetaCodes (
claim_id integer not null,
verification_code char(1) not null default 'm'
check (verification_code = 'm'),
primary key (claim_id, verification_code),
foreign key (claim_id, verification_code)
references Claims (claim_id, verification_code),
other_columns_go_here char(1) not null default 'x'
);
create table CertificateFiles (
claim_id integer not null,
verification_code char(1) not null default 'c'
check (verification_code = 'c'),
primary key (claim_id, verification_code),
foreign key (claim_id, verification_code)
references Claims (claim_id, verification_code),
other_columns_go_here char(1) not null default 'x'
);
begin;
insert into Claims values (1, 'c', 'x');
insert into CertificateFiles values (1, 'c', 'x');
commit;
begin;
insert into Claims values (2, 'e', 'x');
insert into EmailVerifications values (2, 'e', 'x');
commit;
begin;
insert into Claims values (3, 'm', 'x');
insert into MetaCodes values (3, 'm', 'x');
commit;
The overlapping PRIMARY KEY and UNIQUE constraints in "Claims" are required. Other tables reference the pair of columns "claim_id" and "verification_code", and they can't do that unless there's a UNIQUE constraint on the pair of columns.
The verification_code and its CHECK constraints guarantee that the foreign key reference will come from the right table.
-- This insert will fail.
-- Inserting into EmailVerifications requires 'e', not 'c'.
begin;
insert into Claims values (4, 'c', 'x');
insert into EmailVerifications values (4, 'c', 'x');
commit;
-- This insert will fail. (Duplicate row.)
insert into EmailVerifications values (2, 'e', 'x');
-- This insert will fail. (Trying to make two rows reference one row in Claims.)
insert into CertificateFiles values (2, 'e', 'x');