> Does your users table have a few columns prefixed with oidc for single sign-on authentication? Those should probably be in their own table.
If your users have one set of oidc data each, leave it in the users table. There's no such thing as a 1:1 relationship.
So null several columns, perhaps constrain they can only be null (resp. not null) together, ... Or just have a single nullable fk to a table where the data's not nullable.
> Or just have a single nullable fk to a table where the data's not nullable.
Why not the other table having a non-nullable pk/fk to the main table?
https://docs.djangoproject.com/en/4.1/topics/db/examples/one...
yes, orms have a ton of problems, but it's clearly very much a thing.
I don't think it's very elegant and people often forget the unique constraint.
One table is a much better solution.
How does this guarantee that the ID is in both tables?
Create both tables, with the same PK the second with a deferrable, initially deferred foreign key to the first.
Alter the first to add a deferrable, initially deferred foreign key to the second. [Edited to correct swapped table refs in this ¶]
Mission accomplished.
create procedure mandatory_ (_table_name "text", _mandatory_table_name "text") language plpgsql as $$
declare
_trigger_name "text";
begin
_trigger_name = _table_name || '_mandatory_' || _mandatory_table_name || '_trigger';
execute
'create function "' || _trigger_name || '_" () returns trigger language plpgsql as $' || '$ '
'begin '
'if not exists '
'( select 1 '
'from public."' || _mandatory_table_name || '" _mandatory '
'where _mandatory ."' || _table_name || '_id" = new ."id" ) '
'then '
'raise '
'''non-existent relation between "%" and "%" violates mandatory participation constraint'' '
', ' || quote_literal (_table_name) ||
', ' || quote_literal (_mandatory_table_name) || '; '
'end if;'
'return new; '
'end; '
'$' || '$ ';
execute
'create constraint trigger "' || _trigger_name || '" '
'after insert or update on "' || _table_name || '" '
'deferrable initially deferred '
'for each row execute function "' || _table_name || '_mandatory_' || _mandatory_table_name || '_trigger_" () ';
end;
$$;At the database level there's only one kind of foreign key.
Yeah, you can try and prevent it from happening in code or throw some unique constraints at it, but it's unnecessary.
I'd still advise people to follow the rules of normalisation unless there are very strong to deviate.
Yes, you can hack it with a unique constraint, but it's not very elegant.
I'd rather follow the rules of normalisation wherever possible.
Yes, you can try and artificially limit them to 1:1 using constraints but it's a hack.
The correct way to represent a 1:1 relationship in a database is with one table.
Normalization means splitting into multiple tables where it avoids anomalies, redundancy (because it allows inconsistency) is one source of anomaly, but not the only one. 4NF -> 5NF normalizations, for instance, do not (at least, as a generality) remove redundancies. (Neither does DKNF -> 6NF, but I’m not convinced that actually reduces anomalies.)
But the other normal forms reduce redundancy which is what makes inconsistencies possible.
Honestly it cuts both ways, I regularly see databases with enough tables AND enough columns to make them nearly incomprehensible.