PostgreSQL – How to Use a Foreign Key

application-designdatabase-designforeign keypostgresql

I'm creating the following table:

CREATE TABLE fund_identifier
(
    id BIGSERIAL PRIMARY KEY NOT NULL,
    identifier TEXT NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS fund_identifier_pkey ON fund_identifier (id);
CREATE UNIQUE INDEX IF NOT EXISTS fund_identifier_identifier_uindex ON fund_identifier (identifier)

However, I'm not sure what would be the best practice to use identifier as a foreign key. Should I use as reference the value of the foreign key like this:

    CREATE TABLE security_papers (
      id                                        BIGSERIAL,
      fund_identifier                           TEXT,
      as_of_date                                DATE,
          ...
      CONSTRAINT security_papers_fund_identifier_fk FOREIGN KEY (fund_identifier) REFERENCES fund_identifier (identifier)
    }

Or, should I use its id? Like this:

    CREATE TABLE security_papers (
      id                                        BIGSERIAL,
      fund_identifier_id                        BIGSERIAL,
      as_of_date                                DATE,
          ...
      CONSTRAINT security_papers_fund_identifier_fk FOREIGN KEY (fund_identifier) REFERENCES fund_identifier (identifier)
    }

My guess is on the second approach when it comes to the normalization rules. On the logical side, my application would need to look for the id of fund_identifier first, before persisting anything at security_papers table. Right ?

But if I go with the second approach, this would be delegated to the database. Making my application logic, easier to implement.

Please let me know your thoughts, and if I'm missing some concept here. Thank you!

Best Answer

Your table seems to have a perfectly good key candidate (identifier) yet you also create a surrogate key. Why? (I do not hold to the rule that all tables must have a surrogate key.)

However, once you create a surrogate key, that is generally the field used to reference rows in that table. Even when importing outside data that contains the text value in identifier, it is converted to the key value when stored.

In other words, almost without exception, the only place you will find the text identifier values will be in the identifier field of the fund_identifier table. This eliminates ambiguous data and simplifies maintenance.