Design della tabella relazionale per la proprietà dei dati

3

Impostazioni

(schema semplificato per chiarezza)

Supponiamo che abbia una tabella chiamata resource :

+---------------+--------------+------+-----+
| Field         | Type         | Null | Key |
+---------------+--------------+------+-----+
| id            | int(11)      | NO   | PRI |
| name          | varchar(255) | NO   |     |
| owner_id      | int(11)      | NO   |     |
+---------------+--------------+------+-----+

Ogni record di risorse è "posseduto" da un utente definito nella tabella user :

+---------------+--------------+------+-----+
| Field         | Type         | Null | Key |
+---------------+--------------+------+-----+
| id            | int(11)      | NO   | PRI |
| name          | varchar(255) | NO   |     |
+---------------+--------------+------+-----+

Una proprietà delle risorse può essere trasferita ad altri utenti con due metodi diversi:

  1. un proprietario di risorse può richiedere che un altro utente assuma la proprietà della risorsa e la proprietà viene trasferita non appena l'utente accetta la proprietà.
  2. Un utente può richiedere la proprietà dal proprietario corrente di una risorsa, la proprietà viene trasferita non appena il proprietario corrente accetta la richiesta.

In entrambi i casi se la richiesta viene rifiutata dal responsabile dell'approvazione, di quanto non sia stato fatto nulla.

La mia ingenua implementazione delle tabelle necessarie per implementare questi concetti.

transferOwnershipRequest
+------------------------+--------------+------+-----+
| Field                  | Type         | Null | Key |
+------------------------+--------------+------+-----+
| id                     | int(11)      | NO   | PRI |
| resource_id            | int(11)      | NO   |     |
| requested_by_owner_id  | int(11)      | NO   |     |
| approver_owner_id      | int(11)      | NO   |     |
| requested_new_owner_id | int(11)      | NO   |     |
| status_id              | int(11)      | NO   |     |
+------------------------+--------------+------+-----+

transferOwnershipRequestStatus
+---------------+--------------+------+-----+
| Field         | Type         | Null | Key |
+---------------+--------------+------+-----+
| id            | int(11)      | NO   | PRI |
| status        | varchar(10)  | NO   |     |
+---------------+--------------+------+-----+

// status example data
+----+----------+
| id | status   |
+----+----------+
| 1  | pending  |
| 2  | approved |
| 3  | denied   |
+----+----------+

La mia logica aziendale aggiornerebbe transferOwnershipRequest . status_id mentre una richiesta si fa strada attraverso il processo di approvazione.

problema

Vedo immediatamente più problemi con questa implementazione.

  • Non c'è modo di tenere traccia delle variazioni di proprietà nel tempo.
  • I campi di timestamp in transferOwnershipRequest (come last_updated , request_time , approver_response_time ecc.) sono macchinosi
  • Qualsiasi tipo di funzionalità di fallback (come tornare a un proprietario precedente se il proprietario corrente è investito da un bus) sarebbe difficile da implementare.

Domanda

Quali sono le mie opzioni per quanto riguarda i modelli di progettazione di database relazionali per questo tipo di situazione? Hai implementato qualcosa di simile a questo?

    
posta Zach Spencer 16.12.2015 - 23:38
fonte

3 risposte

2

La tua tabella delle richieste sembra corretta, mantienila così com'è, aggiungi semplicemente un concetto generale di "tenere traccia dei record storici" alle altre tabelle , questo risolverà tutti i tuoi tre requisiti aggiuntivi.

Inizia implementando il concetto di proprietà in una tabella separata "proprietà":

+---------------+--------------+------+-----+
| Field         | Type         | Null | Key |
+---------------+--------------+------+-----+
| id            | int(11)      | NO   | PRI |
| resource_id   | int(11)      | NO   |     |
| owner_id      | int(11)      | NO   |     |
+---------------+--------------+------+-----+

(e rimuovi owner_id dalla risorsa).

Ora estendi questo modello aggiungendo una "funzionalità cronologia" alla tabella delle proprietà. Ci sono fondamentalmente due modi standard per fare ciò: o aggiungi un campo timestamp nullable a questa tabella e usa la convenzione "timestamp = null" significa "correntemente valido", "timestamp set" significa "proprietà nel passato". Oppure, crei una tabella shadow "ownership_archive", con esattamente gli stessi attributi della tabella "ownership" più il campo timestamp. Quindi puoi spostare vecchi record di proprietà che non sono più validi dopo l'approvazione di una richiesta a quella tabella.

Se necessario, è possibile implementare una simile "funzionalità della cronologia" per la tabella "risorsa" e la tabella "utenti", ma ciò sarà necessario solo se è necessario tenere traccia della cronologia delle risorse e degli utenti in dettaglio.

Puoi trovare una discussione più ampia sull'archiviazione di dati storici in un database in questa domanda precedente sullo stackoverflow .

    
risposta data 17.12.2015 - 05:47
fonte
2

Perché non acquisire direttamente gli eventi, ad esempio Event Sourcing? Quindi, avresti una tabella degli eventi che funzionerebbe come un file di log di sola aggiunta; le righe sarebbero immutabili una volta scritte. Gli eventi hanno un valore temporale in modo che possano essere ordinati, e il nome dell'evento (richiesta, approvazione, rifiuto, ecc.). (Probabilmente finiresti per mettere tutti i tipi di eventi in una tabella usando la tabella fat). La proprietà viene considerata trasferita quando viene registrato l'evento di approvazione. Se è necessario, è possibile avere uno stato proprietario separato, che riflette la proprietà corrente senza cronologia. (FYI, ho fatto un po 'di questo, ma non in SQL, anche se dovrebbe funzionare anche lì.)

    
risposta data 17.12.2015 - 00:30
fonte
1

Mi sta bene. Aggiungi questi timestamp alla tabella delle richieste e hai una cronologia permanente - assumendo che tutte le risorse entrino in esistenza con una voce corrispondente nella tabella delle richieste. Quindi, se vuoi una cronologia completa, cerca la tabella per l'ID risorsa e questo ti mostrerà la cronologia della proprietà che risale alla creazione della risorsa che sarebbe la prima voce.

Potresti essere in grado di ridurre il numero di colonne nella tabella delle richieste avendo una colonna del tipo di richiesta e quindi un singolo id per il nuovo proprietario in sospeso. Poiché l'ID risorsa è già connesso al proprietario corrente, non è necessario specificarlo.

    
risposta data 17.12.2015 - 05:45
fonte