web-dev-qa-db-fra.com

Horodatage d'insertion et de mise à jour des lignes SQL Server 2008

J'ai besoin d'ajouter deux colonnes à une table de base de données dans SQL Server 2008 R2:

  • createTS - date et heure d'insertion de la ligne
  • updateTS - date et heure de mise à jour de la ligne

J'ai quelques questions:

  1. Quel type de données de colonne dois-je utiliser pour chacun d'eux?
  2. createTS ne doit être défini qu'une seule fois, lorsque la ligne est insérée. Lorsque j'ai essayé le type datetime pour cette colonne et ajouté une valeur par défaut ou une liaison de getdate(), la colonne la valeur a été correctement réglée. Est-ce la meilleure façon d'atteindre l'objectif de cette chronique? J'ai considéré timestamp type de données , mais c'est, à mon avis, presque un terme impropre!
  3. updateTS doit être réglé sur la date et l'heure du moment où la ligne est mise à jour. Dans SQL Server, il n'y a pas ON UPDATE CURRENT_TIMESTAMP (comme dans MySQL), il semble donc que je doive recourir à l'utilisation d'un déclencheur. Est-ce vrai et comment pourrais-je procéder?

Il y a donc un point de départ pour quiconque souhaite répondre à cette question, voici le script create table:

CREATE TABLE [dbo].[names]
(
    [name] [nvarchar](64) NOT NULL,
    [createTS] [datetime] NOT NULL CONSTRAINT [DF_names_createTS]  DEFAULT (getdate()),
    [updateTS] [datetime] NOT NULL,
    CONSTRAINT [PK_names] PRIMARY KEY CLUSTERED 
    (
        [name] ASC
    )
    WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
21
Web User

essayer

CREATE TABLE [dbo].[Names]
(
    [Name] [nvarchar](64) NOT NULL,
    [CreateTS] [smalldatetime] NOT NULL CONSTRAINT CreateTS_DF DEFAULT CURRENT_TIMESTAMP,
    [UpdateTS] [smalldatetime] NOT NULL

)

PS Je pense qu'un petit moment est suffisant. Vous pouvez décider différemment.

Ne pouvez-vous pas le faire au "moment de l'impact"?

Dans Sql Server, cela est courant:

Update dbo.MyTable 
Set 

ColA = @SomeValue , 
UpdateDS = CURRENT_TIMESTAMP
Where...........

Sql Server a un type de données "d'horodatage".

Mais ce n'est peut-être pas ce que vous pensez.

Voici une référence:

http://msdn.Microsoft.com/en-us/library/ms182776 (v = sql.90) .aspx

Voici un petit RowVersion ( synonyme de timestamp ) exemple:

CREATE TABLE [dbo].[Names]
(
    [Name] [nvarchar](64) NOT NULL,
    RowVers rowversion ,
    [CreateTS] [datetime] NOT NULL CONSTRAINT CreateTS_DF DEFAULT CURRENT_TIMESTAMP,
    [UpdateTS] [datetime] NOT NULL

)


INSERT INTO dbo.Names (Name,UpdateTS)
select 'John' , CURRENT_TIMESTAMP
UNION ALL select 'Mary' , CURRENT_TIMESTAMP
UNION ALL select 'Paul' , CURRENT_TIMESTAMP

select *  ,  ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]

Update dbo.Names Set Name = Name

select *  ,  ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]

Peut-être un exemple de travail complet:

DROP TABLE [dbo].[Names]
GO


CREATE TABLE [dbo].[Names]
(
    [Name] [nvarchar](64) NOT NULL,
    RowVers rowversion ,
    [CreateTS] [datetime] NOT NULL CONSTRAINT CreateTS_DF DEFAULT CURRENT_TIMESTAMP,
    [UpdateTS] [datetime] NOT NULL

)

GO

CREATE TRIGGER dbo.trgKeepUpdateDateInSync_ByeByeBye ON dbo.Names
AFTER INSERT, UPDATE
AS

BEGIN

Update dbo.Names Set UpdateTS = CURRENT_TIMESTAMP from dbo.Names myAlias , inserted triggerInsertedTable where 
triggerInsertedTable.Name = myAlias.Name

END


GO






INSERT INTO dbo.Names (Name,UpdateTS)
select 'John' , CURRENT_TIMESTAMP
UNION ALL select 'Mary' , CURRENT_TIMESTAMP
UNION ALL select 'Paul' , CURRENT_TIMESTAMP

select *  ,  ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]

Update dbo.Names Set Name = Name , UpdateTS = '03/03/2003' /* notice that even though I set it to 2003, the trigger takes over */

select *  ,  ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]

Faire correspondre la valeur "Nom" n'est probablement pas judicieux.

Essayez cet exemple plus courant avec une SurrogateKey

DROP TABLE [dbo].[Names]
GO


CREATE TABLE [dbo].[Names]
(
    SurrogateKey int not null Primary Key Identity (1001,1),
    [Name] [nvarchar](64) NOT NULL,
    RowVers rowversion ,
    [CreateTS] [datetime] NOT NULL CONSTRAINT CreateTS_DF DEFAULT CURRENT_TIMESTAMP,
    [UpdateTS] [datetime] NOT NULL

)

GO

CREATE TRIGGER dbo.trgKeepUpdateDateInSync_ByeByeBye ON dbo.Names
AFTER UPDATE
AS

BEGIN

   UPDATE dbo.Names
    SET UpdateTS = CURRENT_TIMESTAMP
    From  dbo.Names myAlias
    WHERE exists ( select null from inserted triggerInsertedTable where myAlias.SurrogateKey = triggerInsertedTable.SurrogateKey)

END


GO






INSERT INTO dbo.Names (Name,UpdateTS)
select 'John' , CURRENT_TIMESTAMP
UNION ALL select 'Mary' , CURRENT_TIMESTAMP
UNION ALL select 'Paul' , CURRENT_TIMESTAMP

select *  ,  ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]

Update dbo.Names Set Name = Name , UpdateTS = '03/03/2003' /* notice that even though I set it to 2003, the trigger takes over */

select *  ,  ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]
20
granadaCoder

Comme alternative à l'utilisation d'un déclencheur, vous pouvez envisager de créer une procédure stockée pour gérer les INSERTs qui prennent la plupart des colonnes en arguments et obtiennent le CURRENT_TIMESTAMP qu'il inclut dans le INSERT final dans la base de données. Vous pouvez faire de même pour le CREATE. Vous pouvez également être en mesure de configurer les choses afin que les utilisateurs ne puissent pas exécuter les instructions INSERT et CREATE autrement que via les procédures stockées.

Je dois admettre que je ne l'ai pas fait moi-même, donc je ne suis pas du tout sûr des détails.

2
nurdglaw