sql >> Database teknologi >  >> RDS >> Oracle

Hvordan administrerer man bedst historiske opslagsværdier i en database?

Der er en teknik kaldet versionering, der har eksisteret i mange år, men som stort set er ubrugelig af flere årsager. Der er dog en lignende teknik, jeg kalder Version Normal Form, som jeg har fundet ud af at være meget nyttig. Her er et eksempel, der bruger en medarbejdertabel.

Først oprettes den statiske tabel. Dette er hovedenhedstabellen, og den indeholder statiske data om enheden. Statiske data er data, der ikke forventes at ændre sig i løbet af enhedens levetid, såsom fødselsdato.

create table Employees(
  ID        int  auto_generated primary key,
  FirstName varchar( 32 ),
  Hiredate  date not null,
  TermDate  date,            -- last date worked
  Birthdate date,
  ...              -- other static data
);

Det er vigtigt at indse, at der er én post for hver medarbejder, ligesom med enhver sådan tabel.

Derefter den tilhørende versionstabel. Dette etablerer et 1-m-forhold til den statiske tabel, da der kan være flere versioner for en medarbejder.

create table Employee_versions(
  ID         int   not null,
  EffDate    date  not null,
  char( 1 )  IsWorking not null default true,
  LastName   varchar( 32 ),    -- because employees can change last name
  PayRate    currency not null,
  WorkDept   int   references Depts( ID ),
  ...,              -- other changable data
  constraint PK_EmployeeV primary key( ID, EffDate )
);

I versionstabelnoten er der en ikrafttrædelsesdato, men ikke et matchende felt, der ikke længere er gyldigt. Dette skyldes, at når en version træder i kraft, forbliver den i kraft, indtil den erstattes af den efterfølgende version. Kombinationen af ​​ID og EffDate skal være unik, så der ikke kan være to versioner for den samme medarbejder, der er aktive på samme tid, og der kan heller ikke være et mellemrum mellem det tidspunkt, hvor en version slutter, og hvornår den næste version starter.

De fleste forespørgsler vil gerne vide den aktuelle version af medarbejderdata. Dette opnås ved at forbinde den statiske række for medarbejderen med den version, der er gældende nu. Dette kan findes med følgende forespørgsel:

select  ...
from    Employees e
join    Employee_versions v1
    on  v1.ID = e.ID
    and v1.EffDate =(
        select  Max( v2.EffDate )
        from    EmployeeVersions v2
        where   v2.ID = v1.ID
            and v2.EffDate <= NOW()
    )
where  e.ID = :EmpID;

Dette returnerer den eneste version, der startede i den seneste fortid. Brug af uligheden <=i datokontrollen (v2.EffDate <= NOW() ) giver mulighed for effektive datoer i fremtiden. Antag, at du ved, at en ny medarbejder starter den første dag i næste måned, eller at en lønforhøjelse er planlagt til den 13. i næste måned, kan disse data indsættes før tid. Sådanne "forudindlæste" poster vil blive ignoreret.

Lad ikke underforespørgslen komme til dig. Alle søgefelter er indekseret, så resultatet er ret hurtigt.

Der er meget fleksibilitet med dette design. Forespørgslen ovenfor returnerer de seneste data for alle medarbejdere, nutid og tidligere. Du kan tjekke TermDate felt for at få netop nærværende medarbejdere. Faktisk, da en hel del steder i dine apps kun vil være interesseret i de aktuelle oplysninger om nuværende medarbejdere, ville den forespørgsel give en god visning (udelad den endelige where klausul). Det er ikke nødvendigt for apps selv at vide, at sådanne versioner eksisterer.

Hvis du har en bestemt dato, og du vil se de data, der var gældende på det tidspunkt, skal du ændre v2.EffDate <= NOW() i underforespørgslen til v2.EffDate <= :DateOfInterest .

Flere detaljer kan findes i en diaspræsentation her og et ikke helt udfyldt dokument her.

For at vise lidt af designets udvidelsesmuligheder skal du bemærke, at der er en IsWorking indikator i versionstabellen samt en ophørsdato i den statiske tabel. Når en medarbejder forlader virksomheden, indsættes sidste dato i den statiske tabel og en kopi af den seneste version med IsWorking indstillet til false er indsat i versionstabellen.

Det er ret almindeligt, at medarbejdere forlader en virksomhed i et stykke tid og derefter bliver ansat igen. Med blot datoen i den statiske tabel, kan indtastningen aktiveres igen blot ved at sætte datoen tilbage til NULL. Men en "tilbageblik"-forespørgsel for ethvert tidspunkt, hvor personen ikke længere var en medarbejder, ville returnere et resultat. Intet tydede på, at de havde forladt virksomheden. Men en version med IsWorking =falsk, når du forlader virksomheden og IsWorking =sand ved tilbagevenden til virksomheden vil tillade en kontrol af denne værdi på interessetidspunktet og ignorere medarbejdere, da de ikke længere var ansat, selvom de vendte tilbage senere.



  1. Sådan fungerer UPPER()-funktionen i MySQL

  2. Sådan fungerer RPAD() i MariaDB

  3. Sådan formateres dato og klokkeslæt i SQL Server

  4. Sådan beregnes månedlig vækst i PostgreSQL