You can avoid duplicating the type definition, but SQL won't deduce the type to use by reading the type of a foreign key reference.
The SQL standard way
CREATE DOMAIN lets you create a domain (duh) which the docs describe as "essentially a data type with optional constraints".
So, in your case, you could do something like this.
create domain CITY_NAME as varchar(80) NOT NULL;
Then, in your table definition, you can use CITY_NAME instead of varchar(80).
CREATE TABLE cities (
city CITY_NAME primary key,
location point
);
CREATE TABLE weather (
city CITY_NAME references cities(city),
temp_lo int,
temp_hi int,
prcp real,
date date
);
PostgreSQL also supports CHECK() constraints as part of the CREATE DOMAIN statement.
If the definition has to change, you can dump the data, change the CREATE DOMAIN statement in one place, drop the database, rebuild the schema, and reload the data. I don't think you can change a domain that's in use, but I could be wrong. I've only had to do that three or four times in 30 years.
The non-standard, codegeek way
The C language has a preprocessor. Languages that lack a preprocessor can use m4.
m4 gives you more flexibility than SQL's CREATE DOMAIN, but it has a broader scope. Sometimes that's a good thing, and sometimes it's not. The most important difference is that m4 will look for a token like "CITY_NAME" everywhere, not just in the places where a data type declaration is expected. A carefully considered naming convention helps a lot.
Define a macro and its substitution. Then write your CREATE TABLE statements just like above.
define(`CITY_NAME', `varchar(80)')
CREATE TABLE cities (
city CITY_NAME primary key,
location point
);
When you run that through m4, you should get a CREATE TABLE statement that has "varchar(80)" in place of "CITY_NAME", like this.
CREATE TABLE cities (
city varchar(80) primary key,
location point
);
city_idas the PK to join the two, rather than a name. There are lots of cities around the world with the same name, so best not use the name as the PK... – Phil Jan 27 at 23:45serial. – Stephane Rolland Jan 27 at 23:49