SQL Server:与Oracle中的RowVersion等效
技术问答
195 人阅读
|
0 人回复
|
2023-09-13
|
Oracle是否具有与SQL ServerRowVersion相似的数据类型?
& K; L# c% _! a e1 x5 E: J) F当您插入或更新一行时,相应的Version列(类型为RowVersion)会自动更新。$ _' @4 m4 }+ z( Z! m9 B( `' t
MSDN说到RowVersion$ b7 Z9 [6 _% B4 J
:
9 t" X6 Z% o% @4 Z3 V- i# o- r; ]/ @ b, Y. D6 M( g1 ^( K5 v. P
*
; W/ P0 Z3 I( ]! ~是一种数据类型,它公开了数据库中自动生成的唯一二进制数。rowversion通常用作版本标记表行的机制。存储大小为8个字节。rowversion数据类型只是一个递增数字,并不保留日期或时间。
6 k3 \9 \# d+ f1 {*
$ u: n3 [# T* l0 U* x$ [3 {每个数据库都有一个计数器,该计数器针对在数据库中包含rowversion列的表上执行的每个插入或更新操作递增。此计数器是数据库行版本。这将跟踪数据库中的相对时间,而不是可与时钟关联的实际时间。一个表只能有一个rowversion列。每次修改或插入具有rowversion列的行时,数据库增量rowversion值都会插入到rowversion列中。
4 ?- e3 H! u% F! ]4 G. o*; x) Q. S q9 O7 d$ k( i" y8 x
您可以使用一行的rowversion列轻松确定自上次读取该行以来,该行中的任何值是否已更改。如果对该行进行了任何更改,则将更新rowversion值。如果未对行进行任何更改,则rowversion值与先前读取的值相同。
9 f* ~- T* e0 f/ f" p* R您可以在表中添加rowversion列,以在多个用户同时更新行时帮助维护数据库的完整性。您可能还想知道多少行以及更新了哪些行而无需重新查询表。& t" P- t$ U3 [2 w. `( y' }3 _
8 ~2 U. ?* @3 c; S1 S* I3 N$ Y8 @5 f( ~# A+ e
我们正在使用oracle设计数据模型,并希望使用Version列来管理并发。
1 a$ w( p) }6 T& P# G+ e% A我也想知道在Oracle世界中是否有更好的方法。4 k5 N3 T w/ Q; r5 }# }, T/ {
5 A) K: w/ ?$ W6 O% j
解决方案:% c2 y5 C$ P5 E0 u1 W5 L+ R' f5 |9 c8 a
4 L& H4 o8 H! ~; @* `4 q X) J
, O. Z! Q& G" V+ L4 y f
! U# x0 _9 t6 u m/ i 简单的答案是“否”-但是使用NUMBER列和设置/更新它的触发器来创建自己很容易。
; I6 [& @1 [) DOracle 11gR2的一个简单示例:' ~, L; b+ b7 d2 V; [( J
CREATE SEQUENCE global_rowversion_seq;
( C4 I5 ~4 I( T) bALTER TABLE mytable1 ADD rowversion NUMBER;# u9 {7 d! b6 U, D0 i
ALTER TABLE mytable2 ADD rowversion NUMBER;& a+ l$ t4 {1 w# @3 i
CREATE TRIGGER mytable1_biu
6 U8 Q! D" ?7 c/ |4 E BEFORE INSERT OR UPDATE! s4 B! @, j: M" B
ON mytable1 u: s* M, ^- L
FOR EACH ROW
* J( ?) C" o; Z/ aBEGIN
3 G/ n* G! f$ L; S :NEW.rowversion := global_rowversion_seq.NEXTVAL;
6 q+ W4 Y' T5 _( P; {END mytable1_biu;
9 u/ d) D1 P4 u% j3 NCREATE TRIGGER mytable2_biu" u/ O" m! ]: B+ f" W2 S4 w
BEFORE INSERT OR UPDATE+ y3 {( j) h: K6 ?
ON mytable2
$ e+ v* W7 e& e; {$ g0 \ } FOR EACH ROW! x5 D8 X. F+ y% y
BEGIN1 K& W0 B. z# P7 f1 R* g6 e2 g# W
:NEW.rowversion := global_rowversion_seq.NEXTVAL;
6 F* ` e5 s+ ? s6 k# [& @( _' ^END mytable2_biu;0 u8 O7 p8 B% E3 [
(如果您使用的是较早的Oracle版本,则触发器中的分配必须通过查询来完成,例如:# C* V. w5 E7 H: {8 a5 n2 u+ N
SELECT global_rowversion_seq.NEXTVAL* k- C) D! H3 [1 N0 |% H* \
INTO :NEW.rowversion* P: }+ I- B/ j" c( {, {% C. m
FROM dual;: d0 X0 }1 o3 c' i+ X
现在,请记住,在某些情况下,由于所有使用相同序列进行数据库插入/更新的争用,该设计在极端情况下(例如,具有极高插入/更新活动的数据库)可能会对性能产生影响。当然,在这种情况下,您可能首先会避免触发。
+ m& r5 x! z& D/ E根据您使用rowversion列的方式,最好对每个表使用单独的序列。当然,这意味着行版本将不再是全局唯一的-
, e7 Q' ]2 y( n但是,如果您仅对比较表中行的更改感兴趣,那么就可以了。 T% n5 s0 r x; s! `
另一种方法是分别为每一行增加计数器-这不需要序列,并且允许您检测到行的更改(但不允许将任何行与另一行进行比较):- V" K: k- ]6 Q N% T/ ~, N
ALTER TABLE mytable ADD rowversion NUMBER;! M6 `) I7 N+ o% J R9 r
CREATE TRIGGER mytable_biu
- f0 }9 o8 J7 x; \. J6 h BEFORE INSERT OR UPDATE
1 y! b" S! z: e- i" u4 O) d. Z ON mytable2 q2 a' q9 C$ T" V3 V8 \
FOR EACH ROW0 c5 g1 G% S5 z6 Z$ n4 E. N, j
BEGIN4 y! O; U+ K9 f+ i' a7 r3 Y3 z
:NEW.rowversion := NVL(:OLD.rowversion, 0) + 1;
* x% j; ~# c3 J; Q4 |. _: K1 J3 QEND mytable_biu;
/ N* Q- | Y9 o+ q0 S$ G6 i每行将以rowversion = 1插入,然后对该行的后续更新会将其递增为2、3,依此类推。 |
|
|
|
|
|