2009-02-17 18 views
5

Esiste un modo speciale per dichiarare una colonna DateCreated in una tabella MS Sql Server in modo che venga automaticamente riempita con la data/ora appropriata quando viene creata?Colonna DateCreated nel server Sql?

Oppure .. devo fornire il datetime ad esso quando faccio la query, manualmente?

risposta

10

È possibile impostare il valore predefinito della colonna su "GETDATE()"

+1

Si noti che questo può essere aggirato dagli utenti poiché il valore predefinito non viene preso in considerazione quando si inserisce un valore effettivo. E può anche essere aggiornato dagli utenti. Probabilmente è abbastanza buono se puoi controllare quale SQL viene eseguito (e non puoi :-) ma non è sicuro. – paxdiablo

+0

Questo è in realtà una buona cosa, perché se un utente ha una data specifica che deve mettere lì probabilmente dovrebbe essere permesso a meno che tu non abbia regole che governano diversamente. – James

+0

Rispettosamente in disaccordo, @James. Non hai mai sentito parlare di Sarbanes-Oxley? :-) Se hai una colonna DateCreated, dovrebbe essere impostata alla data di creazione della riga. Se si desidera una colonna modificabile dall'utente, dovrebbe essere denominata DateCreatedForPurposesOfFraud o qualcosa di simile. – paxdiablo

15

I valori di default soffrono di due grossi inconvenienti.

  • se l'istruzione di inserimento specifica un valore per la colonna, il valore predefinito non viene utilizzato.
  • la colonna può essere aggiornata in qualsiasi momento.

Ciò significa che non è possibile essere certi che i valori non siano stati modificati al di fuori del proprio controllo.

Se si desidera l'integrità dei dati reali (in modo che si sia sicuri che la data nella riga è la data di creazione), è necessario utilizzare i trigger.

Un trigger di inserimento per impostare la colonna sulla data corrente e un trigger di aggiornamento per impedire modifiche a quella colonna (o, più precisamente, impostarlo sul suo valore corrente) sono il modo di implementare una colonna DateCreated.

Un trigger di inserimento e aggiornamento per impostare la colonna sulla data corrente è il modo per implementare una colonna DateModified.

(modifica dall'utente Gabriel - ecco il mio tentativo di attuare questo come descritto - non sono sicuro al 100% che sia corretta ma spero il PO del cliente esso ...):

CREATE TRIGGER [dbo].[tr_Affiliate_IU] 
    ON [dbo].[Affiliate] 
    AFTER INSERT, UPDATE 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    -- Get the current date. 
    DECLARE @getDate DATETIME = GETDATE() 

    -- Set the initial values of date_created and date_modified. 
    UPDATE 
     dbo.Affiliate 
    SET 
     date_created = @getDate 
    FROM 
     dbo.Affiliate A 
     INNER JOIN INSERTED I ON A.id = I.id 
     LEFT OUTER JOIN DELETED D ON I.id = D.id 
    WHERE 
     D.id IS NULL 

    -- Ensure the value of date_created does never changes. 
    -- Update the value of date_modified to the current date. 
    UPDATE 
     dbo.Affiliate 
    SET 
     date_created = D.date_created 
     ,date_modified = @getDate 
    FROM 
     dbo.Affiliate A 
     INNER JOIN INSERTED I ON A.id = I.id 
     INNER JOIN DELETED D ON I.id = D.id 
END 
+0

Se si controlla l'ambiente e l'applicazione, si controlla l'accesso al livello dati. Le due preoccupazioni diventano quindi irrilevanti. –

+0

Davvero, non pensi che qualcuno possa semplicemente connettersi al DBMS con un driver JDBC? E uno dei principali vantaggi di n-tier è che ogni livello è responsabile della propria integrità. Non si assume MAI che il DB sia protetto dall'applicazione quando può proteggersi. Questo sta chiedendo guai. – paxdiablo

+0

@Pax: No, non lo faccio. Una connessione ad-hoc non può connettersi a un ambiente adeguatamente protetto. La sicurezza non è l'unica responsabilità del DMBS (fornisce un punto di partenza) come dovrebbe essere una strategia di cooporate/piattaforma. –

0

Certamente lo è.

Ecco un esempio in azione per voi.

Create table #TableName 
(
    ID INT IDENTITY(1,1) PRIMARY KEY, 
    CreatedDate DATETIME NOT NULL DEFAULT GETDATE(), 
    SomeDate VARCHAR(100) 
) 

INSERT INTO #TableName (SomeDate) 
SELECT 'Some data one' UNION ALL SELECT 'some data two' 

SELECT * FROM #TableName 

DROP TABLE #TableName 
+0

E cosa succede quando un dipendente insoddisfatto arriva con "AGGIORNA #TABLE SET CREATEDDATE = GETDATE()"? Bang, ci sono tutte le tue preziose informazioni su quando sono state create le righe. – paxdiablo

+2

@Pax: non accadrebbe sul mio terreno, tuttavia, nell'improbabile caso in cui lo facesse, avrei semplicemente implementato le nostre procedure DR e recuperato i dati. Sembra che tu debba considerare la tua strategia di sicurezza e il morale del personale :-) –

+1

"Morale", ma forse anche la loro morale dovrebbe essere esaminata :-) Comunque, la prevenzione è sempre meglio del recupero. È la differenza tra nessun tempo di fermo e alcuni tempi di inattività (nessuno è migliore di qualsiasi importo). Probabilmente è più l'ambiente in cui lavoro, DB2 su System z, siamo sempre paranoici. – paxdiablo

2

Abbiamo DEFAULT CreatedDate e non applicano con trigger

Ci sono momenti in cui si vuole impostare la data in modo esplicito - per esempio se importiamo dati da un'altra fonte.

V'è il rischio che Bug applicazione potrebbe pasticciare con la CreateDate, o di un DBA scontento per quella materia (non abbiamo non-DBA collegamento diretto al nostro DB)

Suppongo che si potrebbe impostare colonna- autorizzazioni di livello su CreateDate.

Una via di mezzo potrebbe essere quella di avere un TRIGGER INSERISCI creare una riga in una tabella 1: 1, in modo che la colonna fosse fuori dalla tabella principale. La seconda tabella potrebbe avere autorizzazioni SELECT, in cui la tabella principale dispone delle autorizzazioni UPDATE e quindi non è necessario un trigger UPDATE per impedire modifiche a CreateDate, che rimuoverà un po 'di "peso" durante l'aggiornamento delle righe normalmente.

suppongo che COUL avere un UPDATE/DELETE trigger sul secondo tavolo per prevenire il cambiamento (che non sarebbe mai stato eseguito in circostanze normali, in modo "leggero")

po 'di dolore per avere la tabella in più però ... potrebbe avere una tabella per tutti i CreateDates - TableName, PK, CreateDate.La maggior parte degli architetti di database lo odierà però ...