22

SQL Server 2008 R2 のデータベース テーブルに 2 つの列を追加する必要があります。

  • createTS -行が挿入された日時
  • updateTS -行が更新された日時

いくつかの質問を聞きたいんです:

  1. これらのそれぞれにどの列データ型を採用する必要がありますか?
  2. createTS行が挿入されるときに一度だけ設定する必要があります。この列の型を試し、デフォルト値またはバインディングdatetime追加すると、列の値が適切に設定されました。これが、このコラムの目的を達成する最善の方法ですか? 私はdata typeと考えましたが、私の意見では、それはほとんど誤称です!getdate()timestamp
  3. updateTS行が更新された時点の日時に設定する必要があります。SQL Server には(MySQL のように) ON UPDATE CURRENT_TIMESTAMPがないため、トリガーを使用する必要があるようです。これは正しいですか、どうすればそれを行うことができますか?

したがって、この質問に答えたい人のための出発点があります。テーブル作成スクリプトは次のとおりです。

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]
4

2 に答える 2

21

試す

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

)

PS smalldatetime で十分だと思います。別の方法で決定することもできます。

「インパクトの瞬間」にこれができない?

Sql Server では、これが一般的です。

Update dbo.MyTable 
Set 

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

Sql Server には「タイムスタンプ」データ型があります。

しかし、それはあなたが思うものではないかもしれません。

ここに参照があります:

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

RowVersion ( timestampの同義語) の例を次に示します。

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]

たぶん完全な実例:

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]

「名前」値でのマッチングはおそらく賢明ではありません。

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]
于 2013-06-14T20:18:43.020 に答える
2

トリガーを使用する代わりに、ストアド プロシージャを作成して、INSERTほとんどの列を引数として取り、最終的なデータベースCURRENT_TIMESTAMPに含める を取得する を処理することを検討してください。INSERTに対しても同じことができますCREATE。ユーザーがストアド プロシージャ以外のステートメントをINSERT実行できないように設定することもできます。CREATE

私は実際にこれを自分で行ったことがないので、詳細についてはまったく確信が持てないことを認めなければなりません。

于 2013-06-14T21:08:05.507 に答える