web-dev-qa-db-ja.com

SQL Serverのタイムスタンプタイプの列を比較する

最後のタイムスタンプ以降のデータを取得しようとしています。私のレガシーデータベースでは、すべてのテーブルにrecordStampタイプのタイムスタンプという名前の列があります。これに依存して、前の選択からのmax(recordStamp)の後に変更されたレコードを選択します。

T-SQLを試してみました。しかし、これは平等だけを伝えます。私のオプションは何ですか。

CREATE TABLE Cars (
    id int identity, 
    model varchar(20), 
    brand varchar(20), 
    recordstamp timestamp)

INSERT Cars (model)
VALUES 
('accord'),
('camry'),
('corolla'),
('civic'),
('prius')


--latest recordstamp: 0x0000000001DD8AAF
select * from cars order by recordstamp desc --latest recordstamp: 0x0000000001DD8AAF

--Update a record
Update Cars set brand = 'honda' where model = 'accord'

--I want only the accord in result. 
select * from cars order by recordstamp desc 
1
DHAR

TIMESTAMPは、少なくともSQL Serverにおいて、Microsoftが行った最悪の命名決定です。データに日付や時刻の情報が含まれていないだけでなく、名前の使用は実際にANSI標準に違反しています。

私はずっと前に彼らにキーワードを廃止し、これを常にROWVERSIONと呼ぶように頼みました。ただし、TIMESTAMPを使用して明示的にテーブルを作成した場合でも、ツールとメタデータはROWVERSIONを表示してスクリプト化します。それはひどく誤解を招くものです。

いずれの場合も、この列から日付/時刻情報を導き出す方法、または列情報がnによって変化したときに経過した時間を知る方法はありません。そして、比較しようとしている場合、それをどのように基にしてrecordstampをどのようにして知ることができるかわかりません。孤立したシナリオでは、次のようなことができます。

SELECT *, CONVERT(int, recordstamp) 
  FROM dbo.Cars;

enter image description here

DECLARE @ts int;
SELECT @ts = MAX(convert(int, recordstamp)) FROM dbo.Cars;

UPDATE Cars SET model += 'x' WHERE id = 1;

SELECT *, CONVERT(int, recordstamp) 
  FROM dbo.Cars 
  WHERE recordstamp > @ts;

enter image description here

しかし、テーブルを更新する別のセッションである場合、これをどのように行うのですか?そして、非常に制御された環境の外では、このデータベースが他の場所にバックアップおよび復元された場合、フェイルオーバーされた場合、またはインスタンスが再起動された場合でもどうなるかわかりません。 documentation は増加していることを示していますが、これが永続的であることを明示的に示しておらず、日付/時刻を追跡するためにそれを使用することに対して何らかの警告を発しています。

変更日が重要な場合、正しく実行してください:datetime2列をテーブルに追加し、トリガーで維持します。

2
Aaron Bertrand

これは私のために働く

declare @Cars TABLE  (id int identity, model varchar(20),  brand varchar(20),  recordstamp timestamp);
INSERT @Cars (model)
VALUES 
('accord'),
('camry'),
('corolla'),
('civic'),
('prius');
select * 
from @cars 
order by recordstamp desc;
declare @TS timestamp = (select max(recordstamp) from @cars);
update @Cars set brand = 'honda' where model = 'accord';
select * 
from @cars 
order by recordstamp desc;
select * 
from @cars 
where recordstamp > @TS;

id          model                brand                recordstamp
----------- -------------------- -------------------- ------------------
5           prius                NULL                 0x00000000000007EB
4           civic                NULL                 0x00000000000007EA
3           corolla              NULL                 0x00000000000007E9
2           camry                NULL                 0x00000000000007E8
1           accord               NULL                 0x00000000000007E7


id          model                brand                recordstamp
----------- -------------------- -------------------- ------------------
1           accord               honda                0x00000000000007EC
5           prius                NULL                 0x00000000000007EB
4           civic                NULL                 0x00000000000007EA
3           corolla              NULL                 0x00000000000007E9
2           camry                NULL                 0x00000000000007E8


id          model                brand                recordstamp
----------- -------------------- -------------------- ------------------
1           accord               honda                0x00000000000007EC
0
paparazzo