CREATE TABLE ttable1 OF nothing; CREATE TYPE person_type AS (id int, name text); CREATE TABLE persons OF person_type; CREATE TABLE IF NOT EXISTS persons OF person_type; SELECT * FROM persons; \d persons CREATE FUNCTION get_all_persons() RETURNS SETOF person_type LANGUAGE SQL AS $$ SELECT * FROM persons; $$; SELECT * FROM get_all_persons(); -- certain ALTER TABLE operations on typed tables are not allowed ALTER TABLE persons ADD COLUMN comment text; ALTER TABLE persons DROP COLUMN name; ALTER TABLE persons RENAME COLUMN id TO num; ALTER TABLE persons ALTER COLUMN name TYPE varchar; CREATE TABLE stuff (id int); ALTER TABLE persons INHERIT stuff; CREATE TABLE personsx OF person_type (myname WITH OPTIONS NOT NULL); -- error CREATE TABLE persons2 OF person_type ( id WITH OPTIONS PRIMARY KEY, UNIQUE (name) ); \d persons2 CREATE TABLE persons3 OF person_type ( PRIMARY KEY (id), name WITH OPTIONS DEFAULT '' ); \d persons3 CREATE TABLE persons4 OF person_type ( name WITH OPTIONS NOT NULL, name WITH OPTIONS DEFAULT '' -- error, specified more than once ); DROP TYPE person_type RESTRICT; DROP TYPE person_type CASCADE; CREATE TABLE persons5 OF stuff; -- only CREATE TYPE AS types may be used DROP TABLE stuff; -- implicit casting CREATE TYPE person_type AS (id int, name text); CREATE TABLE persons OF person_type; INSERT INTO persons VALUES (1, 'test'); CREATE FUNCTION namelen(person_type) RETURNS int LANGUAGE SQL AS $$ SELECT length($1.name) $$; SELECT id, namelen(persons) FROM persons; DROP TYPE person_type CASCADE;