9

Ho un sistema CMS che memorizza i dati attraverso tabelle in questo modo:Mantenere la cronologia delle modifiche alla pagina. Un po 'lo fa in questo modo per le revisioni

Entries Table 
+----+-------+------+--------+--------+ 
| id | title | text | index1 | index2 | 
+----+-------+------+--------+--------+ 

Entries META Table 
+----+----------+-------+-------+ 
| id | entry_id | value | param | 
+----+----------+-------+-------+ 

Files Table 
+----+----------+----------+ 
| id | entry_id | filename | 
+----+----------+----------+ 

Entries-to-Tags Table 
+----+----------+--------+ 
| id | entry_id | tag_id | 
+----+----------+--------+ 

Tags Table 
+----+-----+ 
| id | tag | 
+----+-----+ 

Sono nel tentativo di implementare un sistema di revisione, un po' come ha così. Se lo stavo facendo solo per il Entries Table stavo pensando di tenere una copia di tutte le modifiche a quella tabella in una tabella separata. Dato che devo farlo per almeno 4 tabelle (la tabella TAGS non ha bisogno di revisioni), questa non sembra affatto una soluzione elegante.

Come lo fareste?

Si prega di notare che i tabelle Meta sono modellati in EAV (entity-attribute-value).

Grazie in anticipo.

risposta

8

Ciao sto attualmente lavorando su una soluzione a un problema simile, sto risolvendo suddividendo le mie tabelle in due, un tavolo di controllo e una tabella di dati. La tabella di controllo conterrà una chiave primaria e un riferimento nella tabella dei dati, la tabella dei dati conterrà la chiave di revisione incrementale automatica e la chiave primaria della tabella di controllo come una chiave esterna.

prendere la vostra tabella di voci come esempio

Entries Table 
+----+-------+------+--------+--------+ 
| id | title | text | index1 | index2 | 
+----+-------+------+--------+--------+ 

diventa

entries    entries_data 
+----+----------+ +----------+----+--------+------+--------+--------+ 
| id | revision | | revision | id | title | text | index1 | index2 | 
+----+----------+ +----------+----+--------+------+--------+--------+ 

alla tua ricerca

select * from entries join entries_data on entries.revision = entries_data.revision; 

invece di aggiornare la tabella entries_data si utilizza un'istruzione di inserimento e quindi aggiornare il revisione della tabella delle voci con la nuova revisione della tabella delle voci.

Il vantaggio di questo sistema è che è possibile passare a revisioni diverse semplicemente modificando la proprietà di revisione all'interno della tabella di voci. Lo svantaggio è che è necessario aggiornare le query. Attualmente sto integrando questo in uno strato ORM in modo che gli sviluppatori non si preoccupino comunque di scrivere SQL. Un'altra idea con cui sto giocando è che ci sia una tabella di revisione centralizzata che utilizza tutte le tabelle di dati. Ciò consentirebbe di descrivere lo stato del database con un numero di revisione singolo, simile a come funzionano i numeri di revisione di subversion.

+0

Perché qualcuno ha votato la risposta di ejrowley? Sto ancora cercando la migliore soluzione possibile e darò credito dove è dovuto il credito. Ma questo sembra una soluzione valida, no? – Frankie

+0

anche se il tuo sistema non è esattamente quello che sto cercando; Credo che lo schema del tavolo 'Media Wiki' in Edward Williams sia una risposta più vicina in termini di prestazioni e disponibilità; Credo che la tua risposta sia nella linea della risposta di Edwards con schemi migliori, quindi lo accetto. Grazie! – Frankie

6

Date un'occhiata a questa domanda: How to version control a record in a database

perché non hanno un history_table separato per ogni tabella (come per la risposta accettata sulla questione legata)? Questo semplicemente ha una chiave primaria composta del PK delle tabelle originali e il numero di revisione. Dopo tutto, dovrai comunque memorizzare i dati.

+0

la tua risposta è molto interessante. Speciale schema di database 'Media Wiki'. Crea un layer aggiuntivo 'table -> revisions keys -> revisions data' mantenendo la' data table' il più piccolo possibile fornendo al contempo una cronologia delle revisioni e potendo navigare tra le revisioni avanti e indietro, come fa SO. Mi chiedo ancora se c'è un modo più * elegante * per memorizzarlo. – Frankie

1

Per uno dei nostri progetti siamo andati seguente modo:

Entries Table 
+----+-----------+---------+ 
| id | date_from | date_to | 
+----+--------_--+---------+ 

EntryProperties Table 
+----------+-----------+-------+------+--------+--------+ 
| entry_id | date_from | title | text | index1 | index2 | 
+----------+-----------+-------+------+--------+--------+ 

Praticamente complicata, ancora permette di tenere traccia del ciclo di vita completo dell'oggetto. Quindi, per interrogare gli enti attivi stavamo andando per:

SELECT 
entry_id, title, text, index1, index2 
FROM 
Entities INNER JOIN EntityProperties 
ON Entities.id = EntityProperties.entity_id 
AND Entities.date_to IS NULL 
AND EntityProperties.date_to IS NULL 

L'unica preoccupazione era per una situazione con un'entità viene rimossa (così abbiamo messo un date_to lì) e poi restaurato da admin.Usando lo schema dato non c'è modo di tracciare questo tipo di trucchi.

Lo svantaggio generale di qualsiasi tentativo del genere è ovvio: è necessario scrivere tonnellate di TSQL in cui i DB non versione andranno per qualcosa come selezionare A join B.