sql >> Databáze >  >> RDS >> Oracle

Jak navrhnout datový model, který se zabývá současnými zaměstnanci a předpokládanými zaměstnanci?

Vidím několik důvodů, proč k tomu potřebujete dvě tabulky:

  • skuteční zaměstnanci musí mít jméno, oddělení atd., zatímco tyto atributy mohou mít pouze zaměstnanci prognózy
  • budou existovat povinnosti, které mohou mít pouze skuteční zaměstnanci, takže je chcete mít možnost odkazovat samostatně

Zároveň ale chcete zajistit, aby nedocházelo ke střetu ID napříč dvěma tabulkami, protože (doufejme) předpokládaní zaměstnanci se stanou skutečnými zaměstnanci.

Způsob, jak toho dosáhnout, je implementovat strukturu supertypu/podtypu. Máte tedy jednu tabulku ZAMĚSTNANCI, která zaručuje jeden primární klíč, a dvě závislé tabulky pro skutečné a předpokládané zaměstnance. Použití sloupce typu je klíčové, protože zajišťuje, že se daný zaměstnanec objeví pouze v jedné podtabulce.

create table employees
    ( emp_id number not null
      , emp_type varchar2(8) not null
      , constraint emp_pk primary key (emp_id)
      , constraint emp_uk unique (emp_id, emp_type)
      , constraint emp_type_ck check (emp_type in ('FORECAST', 'ACTUAL'));

create table actual_employees
    ( emp_id number not null
      , emp_type varchar2(8) not null
      , name varchar2(30) not null
      , deptno number(2,0) not null
      , sal number(7,2) not null
      , hiredate date not null
      , constraint actemp_pk primary key (emp_id)
      , constraint actemp_type_ck check (emp_type = 'ACTUAL')
      , constraint actemp_emp_fk foreign key (emp_id, emp_type)
                   references emp (emp_id, emp_type) 
                   deferrable initially deferred ;

create table forecast_employees
    ( emp_id number not null
      , emp_type varchar2(8) not null
      , name varchar2(30) 
      , deptno number(2,0) 
      , sal number(7,2) 
      , predicted_joining_date date
      , constraint foremp_pk primary key (emp_id)
      , constraint foremp_type_ck check (emp_type = 'FORECAST')
      , constraint foremp_emp_fk foreign key (emp_id, emp_type)
                   references emp (emp_id, emp_type) 
                   deferrable initially deferred ;

Takže klíče mohou vypadat trochu divně. Nadřazená tabulka má primární klíč i složený jedinečný klíč. Primární klíč zaručuje jedinou instanci EMP_ID. Jedinečný klíč nám umožňuje vytvářet cizí klíče na podřízených tabulkách, které odkazují jak na EMP_ID, tak na EMP_TYPE. V kombinaci s kontrolními omezeními na podřízeném tJe to proto, že odkazují na jedinečný klíč v nadřazené tabulce spíše než na jeho primární klíč. toto uspořádání zajišťuje, že zaměstnanec může být v FORECAST_EMPLOYEES nebo ACTUAL_EMPLOYEES, ale ne v obou.

Cizí klíče jsou odložitelné, aby bylo možné převést prognózované zaměstnance na skutečné zaměstnance. To vyžaduje tři činnosti:

  1. smazání záznamu od FORECAST_EMPLOYEES
  2. vložení záznamu do ACTUAL_EMPLOYEES
  3. změna EMP_TYPE (ale ne EMP_ID) ve skupině ZAMĚSTNANCI.

Synchronizace akcí 2 a 3 je snazší s odloženými omezeními.

Všimněte si také, že další omezení cizího klíče odkazující na ZAMĚSTNANCE by měla používat primární klíč spíše než jedinečný klíč. Pokud vztahu záleží na typu zaměstnance, pravděpodobně by se měl místo toho propojit s podřízenými tabulkami.

Vítejte ve světě datového modelování. Je to jedna velká bolest hlavy. Protože pokusit se vměstnat chaotickou realitu do čistého datového modelu je těžké :potřebujete jasné požadavky, abyste to udělali správně, a pochopení toho, co je nejdůležitější, abyste mohli dělat rozumné kompromisy.

Navrhl jsem přístup supertypu/podtypu na základě vaší další otázky, a protože se zdá být nejlepším způsobem zpracování dvou souborů dat:skutečných zaměstnanců a fiktivních zaměstnanců. Myslím, že s těmito dvěma skupinami je třeba zacházet odlišně. Například bych trval na tom, aby manažeři byli skutečnými zaměstnanci. Toho lze snadno dosáhnout omezením integrity vůči ACTUAL_EMPLOYEES a mnohem obtížnějšího dosáhnout s jedinou tabulkou, která obsahuje oba typy zaměstnanců.

Mít dvě tabulky znamená, že možná generuje více práce s ohledem na synchronizaci jejich struktur. No a co? Je to do značné míry triviální, protože napsat dva příkazy ALTER TABLE je sotva více práce než jeden. Navíc je docela možné, že se nový sloupec vztahuje pouze na skutečné zaměstnance a nemá žádný význam pro prognózované zaměstnance (např. EARNED_COMMISSION, LAST_REVIEW_RATING). V tomto světle díky samostatným tabulkám je datový model přesnější.

Pokud jde o nutnost duplikovat závislé tabulky, jak zdůrazňuje Ollie, jde o nedorozumění. Tabulky, které platí pro všechny zaměstnance bez ohledu na jejich aktuálnost, by měly odkazovat na tabulku ZAMĚSTNANCI, nikoli na její potomky.

Konečně nechápu, proč je udržování historických dat těžší se dvěma tabulkami než pro jednu. Většina žurnálovacího kódu by měla být zcela vygenerována z datového slovníku.

Jsou tři tabulky:

  • ZAMĚSTNANCI – hlavní tabulka zaručující jedinečná EMP_ID
  • ACTUAL_EMPLOYEES – dětský stůl pro lidi, kteří pracují pro vaši společnost
  • FORECAST_EMPLOYEES – dětský stůl pro lidi, které chcete získat do své společnosti

Mějte prosím na paměti, že na základě skromných podrobností, které jste nám poskytli, vyvozuji předpoklady o vaší obchodní logice.

Nyní se mi zdá, že lidé, kteří ještě nepracují pro vaši společnost, by neměli mít žádné přidružené aktivity. V tomto scénáři byste měli jednu tabulku EMPLOYEE_ACTIVITIES, která je potomkem ACTUAL_EMPLOYEES.

Ale možná skutečně máte aktivity pro lidi, kteří neexistují. Takže tady je výběr:jeden stůl nebo dva? Návrh jedné tabulky má EMPLOYEE_TASKS jako potomka hlavní tabulky EMPLOYEES. Návrh dvou tabulek má ACTUAL_EMPLOYEE_TASKS a FORECAST_EMPLOYEE_TASKS jako potomky tabulek ACTUAL_EMPLOYEES a FORECAST_EMPLOYEES.

Který návrh je správný, závisí na tom, zda potřebujete vynutit pravidla týkající se přidělování úkolů. Vaše společnost může mít například pravidlo, které stanoví, že nové zaměstnance mohou najímat pouze skuteční lidé. Bylo by tedy užitečné mít model, který umožňuje přidělování náborových úkolů pouze ACTUAL_EMPLOYEES.

Dobře, přidal jsem sloupce s datem do dvou tabulek. To vám umožní spustit požadovaný přehled.



  1. Jak vložit speciální znaky do databáze?

  2. Je hromadné vkládání SQL Server transakční?

  3. Create oracle package narazeno PLS-00103:Setkal se se symbolem CREATE

  4. MySQL - Problém počítání řádků a levého spojení