最近的項目中需要對上百萬級的數據進行增量抽取操作,因此了解了一下TIMESTAMP的應用,特此記錄
timestamp -- 時間戳:數據庫中自動生成的唯一二進制數字,與時間和日期無關的, 通常用作給表行加版本戳的機制。存儲大小為 8個字節
每個數據庫都有一個計數器,當對數據庫中包含 timestamp 列的表執行插入或更新操作時,該計數器值就會增加。該計數器是數據庫時間戳。這 可以跟蹤數據庫內的相對時間,而不是時鍾相關聯的實際時間。一個表只能有一個 timestamp 列。每次修改或插入包含 timestamp 列的行 時,就會在 timestamp 列中插入增量數據庫時間戳值。這一屬性使 timestamp 列不適合作為鍵使用,尤其是不能作為主鍵使用。對行的任 何更新都會更改 timestamp 值,從而更改鍵值。如果該列屬於主鍵,那么舊的鍵值將無效,進而引用該舊值的外鍵也將不再有效。如果該表在動態游標 中引用,則所有更新均會更改游標中行的位置。如果該列屬於索引鍵,則對數據行的所有更新還將導致索引更新。
使用某一行中的 timestamp 列可以很容易地確定該行中的任何值自上次讀取以后是否發生了更改。如果對行進行了更改,就會更新該時間戳值。如果沒有對行進行更改,則該時間戳值將與以前讀取該行時的時間戳值一致。
使用記錄:
現有源表tmp_a和目標表tmp_b,需要每天都將tmp_a中的修改的數據同步到tmp_b中
--創建源表tmp_a create table tmp_a(a varchar(10),b TIMESTAMP) insert into tmp_a(a) values( 'abc') insert into tmp_a(a) values( '123') --創建目標表tmp_b create table tmp_b(a varchar(10),b TIMESTAMP)
查詢tmp_a和tmp_b數據
--查詢tmp_a SELECT * FROM tmp_a SELECT * FROM tmp_b
結果,最大的值為 0x00000000000084FD
將tmp_a的數據到如tmp_b中
--導入表tmp_b INSERT INTO tmp_b (a,b) SELECT a,b FROM tmp_a
執行后會發現會報錯誤:
消息 273,級別 16,狀態 1,第 2 行
不能將顯式值插入時間戳列。請對列列表使用 INSERT 來排除時間戳列,或將 DEFAULT 插入時間戳列。
查詢資料后得知:timestamp這個值一般都是數據庫自動添加和修改的,相當於自動增長標識一樣(而且執行update修改語句這個字段也會自動更新),所以一般這個字段我們只做查詢操作。如果要更新這個字段則會提示這個錯誤信息:不能更新時間戳列。但是這個字段是可以手動添加的,不過也只能使用DEFALUT字段(default字段為SQL Service數據庫的一個默認值),如果傳入其他值則會提示錯誤信息:不能將顯式值插入時間戳列。請對列列表使用 INSERT 來排除時間戳列,或將 DEFAULT 插入時間戳列
因此需要將timestamp數據進行轉化
修改tmp_b的結構為:
--創建目標表tmp_b create table tmp_b(a varchar(10),b VARBINARY(8))
然后將tmp_a中列b的值轉化為 十六進制字符串
--導入表tmp_b INSERT INTO tmp_b (a,b) SELECT a,CAST(b AS VARBINARY(8)) FROM tmp_a
執行成功,這樣tmp_a和tmp_b數據相同
修改tmp_a中的數據,會發現tmp_a中的列值為‘abc’的列b已修改
UPDATE tmp_a SET a='def' WHERE a='abc' SELECT * FROM tmp_a --結果 a b def 0x0000000000008502 123 0x0000000000008501
對比兩個表的數據,不同的b列數據,則進行更新操作
SELECT * FROM tmp_a ta WHERE ta.b>0x00000000000084FD