J'ai besoin d'ajouter deux colonnes à une table de base de données dans SQL Server 2008 R2:
J'ai quelques questions:
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!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]
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]
Comme alternative à l'utilisation d'un déclencheur, vous pouvez envisager de créer une procédure stockée pour gérer les INSERT
s 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.