2010-01-29 18 views
6

Ho una tabella server sql con una colonna timestamp. C'è un modo per forzare la modifica della colonna timestamp senza un aggiornamento effettivo del record?Come aggiornare la colonna timestamp del server SQL senza modificare i dati record

Il motivo che sto chiedendo è perché voglio che il timestamp del record cambi quando un record è inserito/aggiornato/cancellato in una tabella figlia.

La data/ora potrebbe non essere il modo migliore per farlo. Se no, cosa dovrei fare? Non voglio usare datetime perché non ritengo che sia un buon modo di versionare. Non voglio usare un numero intero, perché non voglio dover leggere il valore per incrementarlo.

Suggerimenti?

+0

datetime viene di solito utilizzato per LastModified columns..is questo qualcosa di diverso o può chiarire il motivo per cui non si desidera utilizzare un DateTime? – dan

+1

Ho letto un articolo sul motivo per cui il tipo di dati DateTime non deve essere utilizzato per il controllo delle versioni e la concorrenza ottimistica. Non riesco a ricordare ogni dettaglio, ma aveva senso al momento. Credo che a causa della precisione del tipo di dati, gli aggiornamenti potrebbero teoricamente verificarsi nella stessa identica causa causando condizioni di gara. –

+0

Solo se data/ora non viene fornita dal database: SQL Server DATETIMEs sono frazioni di secondo: http://msdn.microsoft.com/en-us/library/ms187819.aspx –

risposta

9

Non voglio usare un numero intero, perché non voglio dover leggere il valore per incrementarlo.

UPDATE Table SET 
    IntColumn = IntColumn + 1 

Mentre questo non tecnicamente richiede una lettura, non vedo alcun problema con esso.

Si può sempre e solo aggiornare allo stesso valore:

UPDATE Table SET 
    SomeColumn = SomeColumn 

che attiverà aggiornamento rowversion pure.

AGGIUNTA: Si potrebbe fare una vista con la rowversion massima dei bambini:

SELECT Parent.*, MaxChildRowVersion as ChildVersion 
FROM Parent 
JOIN (
    SELECT ParentId, MAX(RowVersion) as MaxChildRowVersion 
    FROM Child 
    GROUP BY ParentId 
) as Child ON 
    Parent.ParentId = Child.ParentId 

Ma, no, non è possibile aggiornare direttamente una colonna rowversion (anche se si potrebbe implementare il proprio aggiornabile con @@ DBTS, binari (8) e INSTEAD OF trigger ...)

Potresti fornire esempi del tuo ultimo punto? Sembra promettente.

No, davvero non è così. ;) È troppo lavoro quando potresti semplicemente aggiornare allo stesso valore o usare una vista. Quelle sono le 2 opzioni più facili.

Ma, per essere completa, una colonna binaria (8) con un valore predefinito di @@ DBTS (che restituisce il numero di versione del database) e un trigger AFTER UPDATE che aggiorna anche la colonna binaria al nuovo @@ DBTS darti un tipo di psuedo-rowversion che puoi aggiornare manualmente. Non sarebbe più veloce o meglio dell'aggiornamento di qualche altra colonna allo stesso valore.

+0

Puoi fornire esempi del tuo ultimo punto? Sembra promettente. –

1

Hai esaminato l'utilizzo di triggers? Sembra una scelta più naturale per quello che stai cercando.

Ho lavorato a un'applicazione che aveva una data e ora su tutta la linea una volta; esattamente quello che dovevamo fare con loro si è dimostrato un po 'sfuggente, quindi li abbiamo controllati dallo schema. È possibile leggere la data/ora negli oggetti creati in base ai dati e controllare se è cambiata quando si passa all'aggiornamento e al rollback se si vede che i dati sono sporchi, ma si tratta di un gran numero di regole per non ottenere molto guadagno (a almeno nel dominio in cui stavo lavorando).

+0

In realtà ho. Ma ho ancora bisogno di fare qualcosa nel mio trigger per ottenere una colonna timestamp da aggiornare. Questa era la mia domanda. –

0

Quello che ho intenzione di fare, finché non arriva un'idea migliore, è aggiungere una colonna DateTime alla mia tabella genitore chiamata DateChildrenChanged.

Aggiungerò un trigger sulla tabella figlio che imposterà la colonna DateChildrenChanged sul DateTime corrente e quando ciò accade, verrà aggiornata anche la colonna timestamp della tabella padre.

In questo modo sto utilizzando la colonna timestamp per il controllo delle versioni.

Sono ancora molto aperto alle idee.

+0

Penso che sia il modo migliore per andare. Conserva TIMESTAMP/ROWVERSION per il controllo della versione della riga effettiva. Se hai bisogno di versionare le tue righe figlio - anche lì c'è una colonna TIMESTAMP/ROWVERSION –

4

Ronnie,

Prima di tutto la sintassi timestamp è deprecato da Microsoft, quindi è necessario utilizzare rowversion, secondo il rowversion è sempre legato alla riga.

Dalla documentazione:

rowversion

Ogni database ha un contatore che viene incrementato per ogni operazione di inserimento o aggiornamento che viene eseguita su una tabella che contiene una colonna rowversion all'interno Banca dati. Questo contatore è il database rowversion.

Tuttavia, poiché il modo in cui è implementato in SQL server, è necessario utilizzare i trigger per ottenere ciò che si desidera.

Qualcosa di simile a questo:

CREATE TRIGGER tgUpdateParentRowVersion ON ChildTable FOR INSERT, DELETE, UPDATE 
AS 
BEGIN 
    /* 
    * The updates below force the update of the parent table rowversion 
    */ 
    UPDATE ParentTable 
     SET ChildUpdate = ChildUpdate + 1 
    FROM ParentTable a 
    JOIN inserted i on a.pkParentTable = i.fkParentTable 

    UPDATE ParentTable 
     SET ChildUpdate = ChildUpdate - 1 
    FROM ParentTable a 
    JOIN deleted  d on a.pkParentTable = d.fkParentTable 
END 
+0

Per quanto riguarda la deprecazione, pensavo che fosse il contrario: la rowversion era stata deprecata. Potrei sbagliarmi ... –

+0

@Ronnie: tu ** sei ** sbagliato e Paulo ha ragione. TIMESTAMP è stato ritirato perché il suo nome ha causato molta confusione (le persone pensavano che esistesse un modo per riconvertirle in una data e un'ora). ROWVERSION è la nuova strada da percorrere –

+0

Sono corretto. Grazie. –

Problemi correlati