我遇到了SQL Server中的時間戳數據類型。什麼是實際使用時間戳列在sql server中的例子?什麼是實例使用SQL SERVER中的timestamp列?
回答
我已經使用TIMESTAMP
數據類型(ROWVERSION
,SQL2005 +),以避免lost update problem:
丟失的更新問題:一個第二事務的頂部寫入的 第二值的數據項(數據)第一個值由第一個 併發事務寫入,並且第一個值會丟失到其他同時運行的 事務中,這些事務需要按其優先級以 讀取第一個值。讀取錯誤值 的交易以錯誤的結果結束。
舉例:lost update
:
t : User 1 read payment order (PO) #1 (amount 1000)
t+1: User 2 read payment order (PO) #1 (amount 1000)
t+2: User 1 change the amount for PO #1 to 1005
t+3: User 2 change the amount for PO #1 to 1009 (change make by User 1 is lost because is overwritten by change make by User 2)
t+4: The amount is **1009**.
示例:如何防止lost update
:
t : User 1 read payment order (PO) #1 (amount 1000, timestamp 0x00000000000007D1)
t+1: User 2 read payment order (PO) #1 (amount 1000, timestamp 0x00000000000007D1)
t+2: User 1 change the amount for PO #1 to 1005 and it checks if row has the same `timestamp` (column `RW` in this case; 0x00000000000007D1). The check succeeds and the change is `COMMIT`ed. This will change, also, the timestamp (column 'RW'). The new timestamp is 0x00000000000007D4.
t+3: User 2 change the amount for PO #1 to 1009 and it checks if row has the same `timestamp` (column `RW` in this case; 0x00000000000007D4). The checks fails because the initial timestamp (@rw=0x00000000000007D1) is <> than current timestamp (column `RW`=0x00000000000007D4). An error is raised the catch block "intercepts" the error and this transaction is cancelled (`ROLLBACK`).
t+4: The amount {remains|is} **1005**.
示例:How to prevent the lost update
(警告T-SQL腳本:你必須使用兩個SSMS窗口/兩節)
CREATE DATABASE TestRowVersion;
GO
USE TestRowVersion;
GO
CREATE TABLE dbo.PaymentOrder(
PaymentOrderID INT IDENTITY(1,1) PRIMARY KEY,
PaymentOrderDate DATE NOT NULL,
Amount NUMERIC(18,2) NOT NULL,
CreateDate DATETIME NOT NULL DEFAULT (GETDATE()),
UpdateDate DATETIME NULL,
RW ROWVERSION NOT NULL -- R[ow] V[ersion]
);
GO
INSERT dbo.PaymentOrder (PaymentOrderDate,Amount)
VALUES ('2013-07-21',1000);
INSERT dbo.PaymentOrder (PaymentOrderDate,Amount)
VALUES ('2013-07-22',2000);
INSERT dbo.PaymentOrder (PaymentOrderDate,Amount)
VALUES ('2013-07-23',3000);
GO
SELECT * FROM dbo.PaymentOrder;
/*
PaymentOrderID PaymentOrderDate Amount CreateDate UpdateDate RW
-------------- ---------------- ------- ----------------------- ---------- ------------------
1 2013-07-21 1000.00 2013-07-21 09:35:38.750 NULL 0x00000000000007D1
2 2013-07-22 2000.00 2013-07-21 09:35:38.750 NULL 0x00000000000007D2
3 2013-07-23 3000.00 2013-07-21 09:35:38.750 NULL 0x00000000000007D3
*/
GO
-- User 1 (SQL Server Management Studio/SSMS window #1)
-- [t] Client app, user 1: it loads first PO
SET NOCOUNT ON;
GO
DECLARE @PaymentOrderID INT=1; -- parameter
SELECT po.PaymentOrderID,
po.PaymentOrderDate,
po.Amount,
po.RW
FROM dbo.PaymentOrder po
WHERE [email protected];
-- Client app, user 1: during 15 seconds it edit the amount from 1000.00 to 1005.00
WAITFOR DELAY '00:00:15';
GO
-- [t+2] Client app, user 1: it sends this change (new amount) from client app to database server
-- with the old row version value
DECLARE @PaymentOrderID INT=1; -- parameter
DECLARE @rw BINARY(8)=0x00000000000007D1; -- parameter
DECLARE @NewAmount NUMERIC(18,2)=1005.00; -- parameter
BEGIN TRY
BEGIN TRANSACTION
UPDATE dbo.PaymentOrder
SET [email protected]
WHERE [email protected]
AND [email protected]; -- it checks the timestamp (current timestamp versus original timestamp)
DECLARE @rowcount [email protected]@ROWCOUNT; -- How many rows were affected by the last statement (UPDATE in this case) ?
SELECT @rowcount AS [@@ROWCOUNT];
IF @rowcount<>1
RAISERROR('Lost update or row deleted.', 16, 1);
COMMIT TRANSACTION
PRINT 'UPDATE succeded';
END TRY
BEGIN CATCH
IF @@TRANCOUNT>0
ROLLBACK;
DECLARE @ErrMsg NVARCHAR(2002);
SET @ErrMsg=ERROR_MESSAGE();
RAISERROR(@ErrMsg,16,1);
END CATCH;
GO
-- [t+4] Client app, user 1: it reloads first PO
DECLARE @PaymentOrderID INT=1; -- parameter
SELECT po.PaymentOrderID,
po.PaymentOrderDate,
po.Amount,
po.RW
FROM dbo.PaymentOrder po
WHERE [email protected];
GO
-- User 2 (warning: run this script in another SQL Server Management Studio window: File > New Database Engine Query !; SSMS window #2)
-- [t+1] Client app, user 1: it loads first PO
SET NOCOUNT ON;
GO
DECLARE @PaymentOrderID INT=1; -- parameter
SELECT po.PaymentOrderID,
po.PaymentOrderDate,
po.Amount,
po.RW
FROM dbo.PaymentOrder po
WHERE [email protected];
-- Client app, user 1: during 20 seconds it edit the amount from 1000.00 to 1005.00
WAITFOR DELAY '00:00:20';
GO
-- [t+4] Client app, user 1: it sends this change (new amout) from client app to database server
-- with the old row version value
DECLARE @PaymentOrderID INT=1; -- parameter
DECLARE @rw BINARY(8)=0x00000000000007D1; -- parameter
DECLARE @NewAmount NUMERIC(18,2)=1009.00; -- parameter
BEGIN TRY
BEGIN TRANSACTION
UPDATE dbo.PaymentOrder
SET [email protected]
WHERE [email protected]
AND [email protected]; -- it checks the timestamp (current timestamp versus original timestamp)
DECLARE @rowcount [email protected]@ROWCOUNT; -- How many rows were affected by the last statement (UPDATE in this case) ?
SELECT @rowcount AS [@@ROWCOUNT];
IF @rowcount<>1
RAISERROR('Lost update or row deleted.', 16, 1);
COMMIT TRANSACTION
PRINT 'UPDATE succeded';
END TRY
BEGIN CATCH
IF @@TRANCOUNT>0
ROLLBACK;
DECLARE @ErrMsg NVARCHAR(2002);
SET @ErrMsg=ERROR_MESSAGE();
RAISERROR(@ErrMsg,16,1);
END CATCH;
GO
-- [t+4] Client app, user 1: it reloads first PO
DECLARE @PaymentOrderID INT=1; -- parameter
SELECT po.PaymentOrderID,
po.PaymentOrderDate,
po.Amount,
po.RW
FROM dbo.PaymentOrder po
WHERE [email protected];
GO
個
結果對用戶1(金額1000 - > 1005):
PaymentOrderID PaymentOrderDate Amount RW
-------------- ---------------- --------------------------------------- ------------------
1 2013-07-21 1000.00 0x00000000000007D1
@@ROWCOUNT <- Timestamp check succeeds
-----------
1
UPDATE succeded
PaymentOrderID PaymentOrderDate Amount RW
-------------- ---------------- --------------------------------------- ------------------
1 2013-07-21 1005.00 0x00000000000007D4
結果用戶2(金額1000 - > 1009):
PaymentOrderID PaymentOrderDate Amount RW
-------------- ---------------- --------------------------------------- ------------------
1 2013-07-21 1000.00 0x00000000000007D1
@@ROWCOUNT <- Timestamp check fails
-----------
0
Msg 50000, Level 16, State 1, Line 27
Lost update.
PaymentOrderID PaymentOrderDate Amount RW
-------------- ---------------- --------------------------------------- ------------------
1 2013-07-21 1005.00 0x00000000000007D4
注:改變了錯誤消息RAISERROR('Lost update or row deleted.', 16, 1);
讓我們舉一個銷售訂單表來舉例說明什麼時間戳。
create table saleorder (ordernumber int, amount int, timestamp);
insert into saleorder (ordernumber, amount) values (1, 100), (2, 100), (3, 200);
select * from saleorder
注意timestamp列中的數據。 (SQL Server 2005)說:這個(即時間戳)跟蹤數據庫中的相對時間,而不是與時鐘關聯的實際時間......每次修改或插入帶有時間戳列的行時,遞增的數據庫時間戳值被插入到時間戳列中。
讓我們來看看數據如何看起來像:
ordernumber amount timestamp
1 100 0x00000000000007D1
2 100 0x00000000000007D2
3 200 0x00000000000007D3
好吧。訂單1是先添加的,訂單3是最後輸入的。如果我們要更新訂單1的數量會發生什麼?
update saleorder set amount = 200 where ordernumber = 1
select * from saleorder
啊,請注意,訂單1的時間戳現在是0x7D4(Decimal 2004)。相對於其他行,我們知道最近更新了1號訂單。但是,更重要的是,時間戳的價值來自併發寫入時。
ordernumber amount timestamp
1 200 0x00000000000007D4
2 100 0x00000000000007D2
3 200 0x00000000000007D3
比方說,約翰和瑪麗都在銷售訂單3,使用.NET開發的Web應用程序。約翰拉起訂單並進行更改。 John尚未保存數據。瑪麗拉同樣的順序,並改變它。約翰先救。 Mary試圖保存數據。 .NET應用程序可以首先查看瑪麗拉的時間戳是否仍然與數據庫對於訂單3的時間戳相同。
如果Mary用3號訂單拉的時間戳現在不同(因爲John保存的數據和時間戳自動得到更改),.NET應用程序可以提醒Mary並要求她刷新屏幕上的記錄以查看最新更改(或者可能突出顯示屏幕上的更改)。
將時間戳考慮爲行版本。有趣的是,SQL Server的最新版本使用rowversion數據類型,它與timestamp數據類型是同義的。 Documentation of rowversion(SQL Server 2012)有一些有趣的例子。
我已經使用timestamp列來跟蹤數據更改的時間,特別是需要同步到一個或多個移動應用程序的數據。您可以使用timestamp列僅返回自某個時間點以來發生更改的行(通過提供前一個時間戳)。
- 1. Oracle中的SQL Server TIMESTAMP等效物是什麼?
- 2. SQL Server中命名實例的好處是什麼?
- 3. SQL Server 2000中的TimeStamp
- 4. SQL Server 2016列表實例
- 5. timestamp列在sql server中不更新
- 6. SQL Server 2012默認實例的連接字符串是什麼?
- 7. 在SQL Server索引中使用INCLUDE列的優點是什麼?
- 8. Insert into SQL Server timestamp
- 9. SQL Server實例
- 10. SQL Server實例
- 11. SQL Server 2000 - 什麼是「實際行數」?
- 12. SQL Server中uniqueidentifier的用法是什麼?
- 13. 什麼是SQL Server
- 14. 什麼是SQL Server
- 15. 什麼是SQL Server
- 16. 在ASP.NET中列出SQL Server實例
- 17. 什麼是SQL Server中的.sql文件?
- 18. 爲什麼我的實例在SQL Server Management Studio中顯示2012
- 19. 爲什麼SQL Server列總是小寫?
- 20. sql server中的標識列是什麼?和什麼是在SQL Server中的身份類型?
- 21. SQL Server用戶實例
- 22. 在表格中使用rowversion(timestamp)而不是LastModifyOn(DateTime)列的好處是什麼?
- 23. SQL Server實例ID
- 24. SQL Server 2008實例
- 25. 爲什麼在Java EE Application Server中使用單個JVM實例?
- 26. 爲什麼SQL Server實例總是不能在枚舉中顯示?
- 27. 什麼是SQL Server中的IDENTITY_INSERT和MERGE?
- 28. 什麼是SQL Server中的Service Broker?
- 29. 什麼是SQL Server中的char/varchar?
- 30. SQL SERVER 2008中的SID是什麼?
修改日期不會少數,以避免丟失更新問題? – Imad
@Imad:這可能是一個解決方案,但開發人員應該小心更新此列('[Modified Date]')。 'timestamp' /'rowversion'列具有很大的值,當連接執行'UPDATE'語句時,SQL Server數據庫引擎會自動更新它 –