2015-02-03 9 views
6

È possibile creare un "tipo derivato" da un tipo? Come extends in Java.Tipo derivato in PostgreSQL

Per esempio ho bisogno di questi tipi:

create type mytype as (
    f1 int, 
    --many other fields... 
    fn varchar(10) 
); 

create type mytype_extended as (
    f1 int, 
    --many other fields... 
    fn varchar(10), 

    fx int --one field more 
); 

si può vedere che questo è ridondante. Se in futuro cambierò mytype, dovrò cambiare anche mytype_extended.

Ho provato questo:

create type mytype as (
    f1 int, 
    --many other fields... 
    fn varchar(10) 
); 

create type mytype_extended as (
    mt mytype, 

    fx int --one field more 
); 

ma questo porta mytype_extended avere solo 2 campi, mt (un tipo complesso, Credo) e fx, invece di f1, f2... fn, fx.

C'è un modo per realizzare questo?

risposta

5

In PostgreSQL, non v'è alcun tipo di ereditarietà diretta, ma avete alcune opzioni:

1. Table inheritance

È possibile creare ereditate tabelle per creare tipi ereditati (PostgreSQL sarà sempre creare un tipo composito per ogni tavolo, con lo stesso nome):

create table supertable (
    foo int, 
    bar text 
); 

create table subtable (
    baz int 
) inherits (supertable); 

2. Construct views using each other

Perché viste sono (in realtà) tabelle (con rules), viene creato un tipo per ciascuna di esse anche:

create view superview 
    as select null::int foo, 
      null::text bar; 

create view subview 
    as select superview.*, 
      null::int baz 
    from superview; 

3. Type composition

Questo è quello, hai provato. Lei ha più controllo con questo in generale:

create type supertype as (
    foo int, 
    bar text 
); 

create type subtype as (
    super supertype, 
    baz int 
); 

-- resolve composition manually 
select get_foo(v),  -- this will call get_foo(subtype) 
     get_foo((v).super) -- this will call get_foo(supertype) 
from (values (((1, '2'), 3)::subtype)) v(v); 

+1 Vero tipo di ereditarietà?

PostgreSQL's documentation explicitly says, che l'ereditarietà tabella non è il tipo di ereditarietà dello standard:

SQL: 1999 e successivamente definire una caratteristica di ereditarietà tipo, che differisce in molti aspetti delle caratteristiche descritte qui.

Tuttavia, ereditato i tipi di auto-creato della tabella funzionano davvero come veri tipi ereditati (possono essere utilizzati, in cui il tipo di super-può essere utilizzato):

-- if there is a get_foo(supertable) function, 
-- but there is no get_foo(subtable) function: 

select get_foo((1, '2')::supertable); -- will call get_foo(supertable) 
select get_foo((1, '2', 3)::subtable); -- will also call get_foo(supertable) 

SQLFiddle

2

È possibile utilizzare l'ereditarietà della tabella per questo, poiché ogni tabella definisce implicitamente un tipo. Citò CREATE TABLE:

CREATE TABLE crea automaticamente un tipo di dati che rappresenta tipo composito corrispondente ad una riga della tabella. Pertanto, le tabelle non possono avere lo stesso nome di qualsiasi tipo di dati esistente nello stesso schema .

Il vostro esempio, con tavoli:

create table mytype (
    f1 int, 
    --many other fields... 
    fn varchar(10) 
); 

create table mytype_extended(
    fx int 
) inherits (mytype); 

Nel descrivere la tabella con psql:

 
# \d mytype_extended 

     Table "public.mytype_extended" 
Column |   Type   | Modifiers 
--------+-----------------------+----------- 
f1  | integer    | 
fn  | character varying(10) | 
fx  | integer    | 
Inherits: mytype 

Ora aggiungiamo una colonna alla tabella di base e verificare che la tabella ereditata ottiene too:

alter table mytype add other_column int; 
 
# \d mytype_extended 
      Table "public.mytype_extended" 
    Column |   Type   | Modifiers 
--------------+-----------------------+----------- 
f1   | integer    | 
fn   | character varying(10) | 
fx   | integer    | 
other_column | integer    | 
Inherits: mytype