sqloracle-databasedatabase-designone-to-one

How to create and insert into a table in SQL entity that has two mutually exclusive 1:1 relations?


enter image description here

enter image description here

How do I handle the code for creating these tables and inserting into them?

Tried this but failed :

create table vlasnik
(
    vlasnik_id integer not null constraint vlasnik_pk primary key,
    datum_zakupa date not null
);

create table pravna_osoba
(
    naziv varchar2(20) not null,
    ime_ravnatelja varchar2(20) not null,
    prezime_ravnatelja varchar2(20) not null,
    datum_osnutka date not null,
    OIB_tvrtke varchar2(13) not null,
    pravna_osoba_id number not null 
        constraint pravna_osoba_pk references vlasnik (vlasnik_id) primary key
);

create table fizicka_osoba
(
    ime varchar2(20) not null,
    prezime varchar2(20) not null,
    OIB varchar2(13) not null,
    datum_rodenja date not null,
    primarna_djelatnost varchar2(30) not null,
    broj_sticenika integer not null,
    fizicka_osoba_id number not null  
        constraint fizicka_osoba_pk references vlasnik (vlasnik_id) primary key
);

alter table vlasnik 
    add (constraint vlasnik_pravna_osoba_fk 
         foreign key (PRAVNA_OSOBA_ID) references PRAVNA_OSOBA (PRAVNA_OSOBA_ID),
         constraint vlasnik_fizicka_osoba_fk 
         foreign key (FIZICKA_OSOBA_ID) references FIZICKA_OSOBA (FIZICKA_OSOBA_ID));

Solution

  • From my point of view, you're doing it wrong.

    If you wanted to alter table vlasnik the way you put it, then it should also contain two additional columns: pravna_osoba_id and fizicka_osoba_id because you're trying to apply foreign key constraint on columns that don't exist. That's not a problem. Then, in alter table vlasnik, you'd add initially deferred deferrable clause to make the whole thing work (as Thorsten commented):

    SQL> create table vlasnik
      2  (
      3      vlasnik_id integer not null constraint vlasnik_pk primary key,
      4      pravna_osoba_id number not null,
      5      fizicka_osoba_id number not null,
      6      datum_zakupa date not null
      7  );
    
    Table created.
    
    SQL> create table pravna_osoba
      2  (
      3      naziv varchar2(20) not null,
      4      ime_ravnatelja varchar2(20) not null,
      5      prezime_ravnatelja varchar2(20) not null,
      6      datum_osnutka date not null,
      7      OIB_tvrtke varchar2(13) not null,
      8      pravna_osoba_id number not null
      9          constraint pravna_osoba_pk references vlasnik (vlasnik_id) primary key
     10  );
    
    Table created.
    
    SQL> create table fizicka_osoba
      2  (
      3      ime varchar2(20) not null,
      4      prezime varchar2(20) not null,
      5      OIB varchar2(13) not null,
      6      datum_rodenja date not null,
      7      primarna_djelatnost varchar2(30) not null,
      8      broj_sticenika integer not null,
      9      fizicka_osoba_id number not null
     10          constraint fizicka_osoba_pk references vlasnik (vlasnik_id) primary key
     11  );
    
    Table created.
    
    SQL> alter table vlasnik
      2      add (constraint vlasnik_pravna_osoba_fk
      3           foreign key (PRAVNA_OSOBA_ID) references PRAVNA_OSOBA (PRAVNA_OSOBA_ID)
      4           initially deferred deferrable,
      5           constraint vlasnik_fizicka_osoba_fk
      6           foreign key (FIZICKA_OSOBA_ID) references FIZICKA_OSOBA (FIZICKA_OSOBA_ID)
      7           initially deferred deferrable);
    
    Table altered.
    

    Inserting:

    SQL> insert into vlasnik (vlasnik_id, pravna_osoba_id, fizicka_osoba_id, datum_zakupa)
      2  values (1, 1, 1, sysdate);
    
    1 row created.
    
    SQL> insert into fizicka_osoba (ime, prezime, oib, datum_rodenja, primarna_djelatnost,
      2    broj_sticenika, fizicka_osoba_id)
      3    values ('Little', 'Foot', '123', sysdate, 'None', 111, 1);
    
    1 row created.
    
    SQL> insert into pravna_osoba (naziv, ime_ravnatelja, prezime_ravnatelja, datum_osnutka,
      2    oib_tvrtke, pravna_osoba_id)
      3    values ('Moja firma d.o.o.', 'Big', 'Foot', sysdate, '456', 1);
    
    1 row created.
    
    SQL> commit;
    
    Commit complete.
    

    That's it.


    However: why are you doing it that way?

    So: here's my suggestion, see if it helps or not. If not, switch back to your own idea now that you know how to properly set foreign key constraints.

    SQL> create table osoba
      2    (osoba_id       integer constraint osoba_pk primary key,
      3     oib            varchar2(13) not null,
      4     vrsta          varchar2(1) constraint ch_osoba_vrsta check (vrsta in ('F', 'P')),
      5     naziv          varchar2(50) not null,
      6     ravnatelj      varchar2(50),
      7     datum          date not null,
      8     djelatnost     varchar2(30),
      9     broj_sticenika number,
     10    --
     11    constraint ch_rav check ((vrsta = 'F' and ravnatelj      is     null) or
     12                             (vrsta = 'P' and ravnatelj      is not null)),
     13    constraint ch_dje check ((vrsta = 'F' and djelatnost     is     null) or
     14                             (vrsta = 'P' and djelatnost     is not null)),
     15    constraint ch_sti check ((vrsta = 'F' and broj_sticenika is     null) or
     16                             (vrsta = 'P' and broj_sticenika is not null))
     17    );
    
    Table created.
    
    SQL> comment on column osoba.vrsta is 'F - fizicka, P - pravna osoba';
    
    Comment created.
    
    SQL> comment on column osoba.naziv is 'Naziv pravne osobe ili ime i przeime fizicke osobe';
    
    Comment created.
    
    SQL> comment on column osoba.ravnatelj is 'Ime i prezime ravnatelja (samo za pravne osobe)';
    
    Comment created.
    
    SQL> comment on column osoba.datum is 'Datum osnutka pravne, odn. rodjenja fizicke osobe';
    
    Comment created.
    
    SQL> comment on column osoba.djelatnost is 'Primarna djelatnost (samo za pravne osobe)';
    
    Comment created.
    
    SQL> comment on column osoba.broj_sticenika is 'Samo za pravne osobe';
    
    Comment created.
    
    SQL> create table vlasnik
      2    (vlasnik_id   integer constraint vlasnik_pk primary key,
      3     osoba_id     integer constraint fk_vl_oso references osoba (osoba_id) not null,
      4     datum_zakupa date not null
      5    );
    
    Table created.
    

    A few inserts (intentionally wrong - checking whether check constraints work): fizica osoba first:

    SQL> insert into osoba (osoba_id, oib, vrsta, naziv, ravnatelj, datum, djelatnost, broj_sticenika)
      2    values (1, '123', 'F', 'Little Foot', 'Rav Natelj', sysdate, null, 2);
    insert into osoba (osoba_id, oib, vrsta, naziv, ravnatelj, datum, djelatnost, broj_sticenika)
    *
    ERROR at line 1:
    ORA-02290: check constraint (SCOTT.CH_STI) violated
    
    
    SQL> insert into osoba (osoba_id, oib, vrsta, naziv, ravnatelj, datum, djelatnost, broj_sticenika)
      2    values (1, '123', 'F', 'Little Foot', 'Rav Natelj', sysdate, null, null);
    insert into osoba (osoba_id, oib, vrsta, naziv, ravnatelj, datum, djelatnost, broj_sticenika)
    *
    ERROR at line 1:
    ORA-02290: check constraint (SCOTT.CH_RAV) violated
    
    
    SQL> insert into osoba (osoba_id, oib, vrsta, naziv, ravnatelj, datum, djelatnost, broj_sticenika)
      2    values (1, '123', 'F', 'Little Foot', null, sysdate, null, null);
    
    1 row created.
    

    Pravna osoba:

    SQL> insert into osoba (osoba_id, oib, vrsta, naziv, ravnatelj, datum, djelatnost, broj_sticenika)
      2    values (2, '456', 'P', 'Big Foot', 'Rav Natelj', sysdate, null, 2);
    insert into osoba (osoba_id, oib, vrsta, naziv, ravnatelj, datum, djelatnost, broj_sticenika)
    *
    ERROR at line 1:
    ORA-02290: check constraint (SCOTT.CH_DJE) violated
    
    
    SQL> insert into osoba (osoba_id, oib, vrsta, naziv, ravnatelj, datum, djelatnost, broj_sticenika)
      2    values (2, '456', 'P', 'Big Foot', 'Rav Natelj', sysdate, 'Dje latnost', 2);
    
    1 row created.
    

    Vlasnik:

    SQL> insert into vlasnik (vlasnik_id, osoba_id, datum_zakupa)
      2    values (10234, 1, sysdate);
    
    1 row created.
    
    SQL>