[ Log On ]
ว่ากันด้วยเรื่องของ TIMESTAMP.. มันจำเป็นมั้ย?

หลายๆ ครั้งที่ได้รับคำถามว่า "แปลงค่า timestamp เป็น datetime ยังไงอ่ะลวกเพี่ย?"

หลายๆ ครั้งที่ตอบกลับไปว่า "เมิงจะบ้าหรอ?!?!??!" :D

timestamp คือ Data Type ใน Microsoft SQL Server ครับ มันคือ Data Type ที่เอาไว้ระบุเวอร์ชั่นของข้อมูลแถวนั้นๆ (Row) จริงๆ แล้วมันคือ Row Version นั่นแหละครับ ผมแอบสงสัยเหมือนกันว่าทำไมไม่ตั้งชื่อเป็น rowversion ซะตั้งนานแล้ว เพิ่งจะมาเปลี่ยนกันก็ตอน SQL Server 2005 นี่เอง

Microsoft เค้าเปลี่ยนเป็น ROWVERSION แล้วนะ!

แต่หลายๆ คนที่ผมรู้จักก็ยังนิยมใช้ timestamp กันอยู่ เหตุผลเดียวที่ timestamp ยังคงอยู่ใน SQL Server ก็เพราะเรื่อง Backward Compatibility เท่านั้นเอง แล้วก็ใช้เหล่า MVP และกองทัพ engineer ของ MS คอยแจ้งข่าวตาม blog และ board ต่างๆ 

แต่ก็ยังคงมีคนใช้ timestamp พอๆ กับที่ปัจจุบันนี้ยังมีคนใช้ IE6 ! ของใหม่ที่ดีกว่า "มีให้ใช้" แต่ก็ไม่ยอมเปลี่ยนไปใช้กัน แล้วก็มานั่งบ่นๆ ว่า IE ห่วยงั้นงี๊.. ผมก็งงก่ะลอจิคแบบนี้อยู่ไม่น้อย -*-

ถามว่าควรเปลี่ยนมั้ย? ข้อมูลใน MSDN หน้านี้ ระบุว่า timestamp ล้าสมัย และจะถูกปลดระวางออกจาก Microsoft SQL Server ในอนาคต (อาจจะยังไม่ใช่ SQL Server 2012 แต่ก็น่าจะอีกไม่นานเกินรอ).. เพราะฉะนั้น เปลี่ยนได้ก็รีบเปลี่ยนซะถ้ามีโอกาส

ROWVERSION ดีกว่า TIMESTAMP ยังไง?

มันเหมือนกันเลยครับ แค่เปลี่ยนชื่อเพื่อความเข้าใจใหม่ ขนาดของมันยังคงที่ 8 bytes เท่าเดิม และไม่ได้เก็บเป็น "วันที่-เวลา" เหมือนที่หลายๆ คนเข้าใจกัน ความแตกต่างระหว่าง rowversion กับ timestamp มีอีกนิดนึงครับ ตรงที่ syntax ในการสร้าง

ปกติแล้วเวลาเราจะสร้าง timestamp ใน table ใดๆ เราไม่จำเป็นต้องระบุชื่อ column เพราะยังไงซะ 1 table ก็มีได้แค่ timestamp เดียวเท่านั้น เช่น

CREATE TABLE Person (Id uniqueidentifier PRIMARY KEY, timestamp);

ถ้าใช้คำสั่งนี้ SQL Server จะทำการสร้าง column ที่ชื่อ timestamp ให้โดยอัตโนมัติ แต่ rowversion นั้น เราจำเป็นต้องระบุชื่อ column ด้วย ดังนี้

CREATE TABLE Person (Id uniqueidentifier PRIMARY KEY, Version rowversion);

คำสั่งนี้จะทำการสร้าง column ชื่อ Version ขึ้นมา ซึ่งกำหนด Data Type เป็น rowversion

ROWVERSION กับ Code First

rowversion แบบ nonnullable จะเทียบได้กับ binary(8) ส่วนแบบ nullable จะเทียบได้กับ varbinary(8) สามารถ map กับ Code First property แบบ byte[] ได้

การระบุโดยใช้ Fluent API ทำได้แบบนี้

Property(c => c.Version).IsRowVersion();

แต่สำหรับ Data Annotation นั้น ยังคงใช้ [Timestamp] attribute อยู่ครับ เช่น

[Timestamp]
public byte[] Version { get; set; }

แล้วตกลงว่าเราจะต้องมี ROWVERSION ในทุกๆ Table มั้ย?

ส่วนตัวแล้วผมชอบที่จะมีเอาไว้ใน table สำคัญๆ เช่น ถ้ามี Order กับ OrderItem ผมก็จะมี rowversion อยู่ใน Order เท่านั้น เพราะยังไงซะ เวลาจะ update ข้อมูลอะไรใน OrderItem ผมก็จะต้องเช็คผ่าน Order ก่อนอยู่ดี แต่ถ้าในกรณีที่คุณมีความจำเป็นที่จะสามารถทำการ update ใน OrderItem โดยไม่ผ่าน Order .. คุณก็สามารถมี rowversion ใน OrderItem ได้เช่นกัน

ทั้งนี้ทั้งนั้น มันขึ้นอยู่กับทิศทางการเขียนโปรแกรมของคุณเอง ว่าจะให้ flow มันเป็นอย่างไร

Happy Coding! :)