Foreign key of serial type - ensure always populated manually

懵懂的女人 提交于 2020-01-02 23:15:34

问题


I have two tables: countries and regions.

CREATE TABLE Countries(
    id     SERIAL,
    name   VARCHAR(40) NOT NULL,
    PRIMARY KEY(id)
)

CREATE TABLE Regions(
    id           SERIAL,
    countryId    SERIAL,
    name         VARCHAR(40) NOT NULL,
    PRIMARY KEY(id       ),
    FOREIGN KEY(countryId) REFERENCES Countries(id)
)

When I insert into regions, I would hope that if I fail to mention countryId, I would be stopped, however, countryId is automatically incremented. Is there any way I can be stopped automatically to make this insertion?

Following table where I set countryID as SERIAL NOT NULL doesn't solve the issue.

CREATE TABLE Pigeons(
    id           SERIAL,
    countryId    SERIAL NOT NULL,
    name         VARCHAR(40) NOT NULL,
    PRIMARY KEY(id       ),
    FOREIGN KEY(countryId) REFERENCES Countries(id)
)

The following solves the problem but I would think that it's technically incorrect because my serial could be bigger than 2^31, but int will never be >= 2^31.

CREATE TABLE Legions(
    id           SERIAL,
    countryId    INT NOT NULL,
    name         VARCHAR(40) NOT NULL
    PRIMARY KEY(id       ),
    FOREIGN KEY(countryId) REFERENCES Countries(id)
)

What's the right approach here?


回答1:


I would suggest:

CREATE TABLE country(
    country_id serial PRIMARY KEY
  , country    text NOT NULL
);

CREATE TABLE region(
    region_id  serial PRIMARY KEY
  , country_id int NOT NULL REFERENCES country
  , region     text NOT NULL
);
  • Don't use CaMeL case names. Read the manual about identifiers.
  • Use proper names. Never id or name, which are not descriptive.
  • The underlying type of a serial is integer. Make the referencing column integer.
    Due to the foreign key reference region.country_id can only hold values that are present in country.country_id (or NULL). Your considerations about values > 2^31 are uncalled for.
  • Demonstrating shorter syntax for PK and FK definition (optional). Read the manual on CREATE TABLE.

Code example with more advice:

  • How to implement a many-to-many relationship in PostgreSQL?



回答2:


The right aproach is to read the manual.

The data types serial and bigserial are not true types, but merely a notational convenience for creating unique identifier columns (similar to the AUTO_INCREMENT property supported by some other databases). In the current implementation, specifying:

CREATE TABLE tablename ( colname SERIAL ); is equivalent to specifying:

CREATE SEQUENCE tablename_colname_seq;

CREATE TABLE tablename ( colname integer NOT NULL DEFAULT nextval('tablename_colname_seq') );

ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;

SERIAL is basically an autoincrementing integer. If your data is bigger than int you should use bigint and countries table should use BIGSERIAL.



来源:https://stackoverflow.com/questions/25020178/foreign-key-of-serial-type-ensure-always-populated-manually

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!