问题
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
orname
, which are not descriptive. - The underlying type of a serial is
integer
. Make the referencing columninteger
.
Due to the foreign key referenceregion.country_id
can only hold values that are present incountry.country_id
(orNULL
). 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