2017-01-17 7 views
0

既存のSQL Serverデータベーステーブルにタイムスタンプ列(datetime2)を追加する必要があります。私が列を作成し、getdate()をデフォルト値として使用すると、重複した値が得られます。 datetime2は高精度なレベルを持っているので、それを排除すると思った。エンジンは、私がしたいと思うほど速すぎるかもしれません。SQL Serverでは、レコードを含むテーブルを変更し、各行に一意のdatetime2列を追加するにはどうすればよいですか?

私はINSERT SELECTを使用することはできません。テーブル間に同じ数の列を配置する必要があるからです。前の表には元の問題であるdatetime2が必要なので、私はSELECT INTOを実行できません。私はまた、私が列を作成したのと同時にインデックスを作成しようとしました。重複がインデックスの前に作成され、インデックスが重複を許可しないように設定されているため、できませんでした。私は試した。これらは失敗しました。

テーブルを変更して新しいdatetime2列を追加し、getdate()(またはその他の日付/時刻関数)のすべての一意の値を入力するにはどうすればよいですか?

編集:私が試したVamsiさんのコメントに基づいて:

INSERT 
SELECT 
WAITFOR DELAY '00:00:10.000' 

The duplicate key value is (2017-01-17 11:59:03.7030000) 

私は重複を得ていたので、私は何か間違ったことをやって受け取ります。

編集:私はこれをしなかったバージルさん(感謝)の回答を笑いに基づいて、

DECLARE @dt datetime2(7), 
    @dt2 datetime2(7), 
    @create_dt datetime2(7) 
declare db_cursor cursor for 
select create_dt from mytable; 
    OPEN db_cursor 
FETCH NEXT FROM db_cursor 
INTO @create_dt 
WHILE (@@FETCH_STATUS = 0) 
begin 
    SET @dt = GETDATE() 
    WHILE @dt = @dt2 
    BEGIN 
     WAITFOR DELAY '00:00:00.123' 
     SET @dt = GETDATE() 
    END 
     update mytable set create_dt = @dt where current of db_cursor 
    set @dt2 = @dt 
    FETCH NEXT FROM db_cursor into @create_dt 
end 
close db_cursor 
deallocate db_cursor 
+0

一つの方法は、nullとしてDATETIME2列を作成列にヌルではないでカラム一旦ユニーク日時値を挿入する遅延機能を使用することで、変化させますnullでない列 – vamsi

答えて

1

これは、それはあなたがあれば延長することができ、遅延のビットを付加ので、カーソルが実際に有用である1時間です必要です。

DECLARE @dt datetime2(7), 
    @dt2 datetime2(7) 

DECLARE @MyTableID int 

SET @dt = getdate() 
SET @dt2 = GETDATE() 

DECLARE cx CURSOR FOR 
SELECT MyTableID 
FROM MyTable 
WHERE MyDateTimeColumn IS NULL 
FOR UPDATE OF MyDateTimeColumn 

Open cx 
FETCH NEXT FROM cx 
    INTO @MyTableID 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @dt = GETDATE() 
    WHILE @dt = @dt2 
    BEGIN 
     WAITFOR DELAY '00:00:00.001' 
     SET @dt = GETDATE() 
    END 
    UPDATE MyTable 
    SET MyDateTimeColumn = @dt 
    WHERE CURRENT OF cx 

    SET @dt2 = @dt 
    FETCH NEXT FROM cx 
     INTO @MyTableID 
END 
CLOSE cx 
DEALLOCATE cx 
1

より迅速なオプションは、重複したセットを準備して一意にすることです。

これには2通りの方法があります。

  1. 一意の日付をパラレルテーブルに準備してからコピーします。
  2. 重複を許可し、レコードを挿入してデータを一意の値に変更し、列を一意に変更します。以下

サンプルコード:

--Create a holding table 
DROP TABLE dbo.TimeTest 
CREATE TABLE dbo.TimeTest(ID BIGINT IDENTITY(1,1) 
          ,Val Float 
          ,Dtm DATETIME2 DEFAULT(GETDATE()) 
          ); 
GO 

--Insert Test Data (creating duplicates) 
INSERT INTO dbo.TimeTest(Val) VALUES(RAND()) 
GO 1000 

--Show duplicate values 
SELECT * FROM dbo.TimeTest ORDER BY ID 

--Remove the Duplication 
;WITH cte AS (
SELECT 
    A.Dtm 
    ,ROW_NUMBER() OVER(PARTITION BY Dtm ORDER BY ID) AS Rnk 
FROM 
    dbo.TimeTest A 
    ) 
UPDATE cte 
SET 
    Dtm = DATEADD(MICROSECOND,Rnk-1,Dtm) 

ALTER TABLE dbo.TimeTest ADD CONSTRAINT Dtm UNIQUE(Dtm) 

--Show unique values 
SELECT * FROM dbo.TimeTest ORDER BY ID 
関連する問題