1
sql server
2000
触发器,表同步更新的问题
2
有三个表,A ,B,C
3
A、B表中含有: A1,B1,C1 三个字段,
4
C 表中存放A、B表中的A1、B1、C1 的集合,
5
字段类型都为nvarchar(
10
),
6
当表A的数据被更新、删除、插入后要反映到C表。
7
当表B的数据被更新、删除、插入后要反映到C表。
8
假定A,B表中在a1,b1,c1上有唯一索引
9
10
11
这个问题如果纯属从理论来说,是很容易解决的,因为从要求可知,实质上C表存放的数据即为A、B表的并集。可以在A、B表上创建相同的trigger,一旦A、B表上有变化,比如插入、删除或更新时,即清空C表数据,然后把A、B表的数据union后插入C表中即可实现目的:)呵呵呵。。。
12
13
下面的trigger的实现原理是:
14
15
当A表插入数据时,检查C表中是否有A表将要插入的数据,如果无,则将这行数据插入到C表中,反之,则不需要操作。
16
17
当A表update时, 检查B表中是否有更新前这行数据,如果有,则C表中应该保留这行数据且把A表中更新后的数据也插入到C表中去。如果B表中没有A表更新前的这行数据且C表中没有A表更新后的这行数据,则需要用A表更新后的数据来更新C表中与A表更新前这行数据相同的数据;如果B表中没有A表更新的的这行数据且C表中有A表更新后的这行数据,则需要从C表中删除跟A表更新前相同的那行数据(因为更新A表后,A表和B表都没有A表更新前的那行数据了,则这行数据显然在C表中不应该再存在了)。
18
19
当A表中删除时,检查B表是否还存在A表要删除的这行数据,如果有,则不能删除C表中与A表要删除的数据相同的行。反之,则执行删除操作。
20
21
22
B表中的trigger跟A表中的原理相同。
23
24
25
CREATE
TRIGGER
SYNC_C_BY_A
26
ON
A
27
AFTER
INSERT
,
UPDATE
,
DELETE
28
AS
29
Declare
@Dml
TinyInt
--
1:Insert 2:Update 3:Delete
30
Declare
@RowsD
Int
31
Declare
@RowsI
Int
32
Declare
@A1_D
nvarchar
(
10
)
33
Declare
@B1_D
Nvarchar
(
10
)
34
Declare
@C1_D
Nvarchar
(
10
)
35
--
确定是哪一种dml操作
36
Select
@RowsD
=
Count
(
*
)
From
Deleted
37
Select
@RowsI
=
Count
(
*
)
From
Inserted
38
If
@RowsD
=
0
And
@RowsI
=
0
39
Goto
Exit_
40
If
@RowsD
=
0
And
@RowsI
>
0
41
Set
@Dml
=
1
42
Else
43
If
@RowsD
>
0
And
@RowsI
>
0
44
Set
@Dml
=
2
45
Else
46
If
@RowsD
>
0
And
@RowsI
=
0
47
Set
@Dml
=
3
48
IF
@DML
=
1
49
BEGIN
50
--
检查c表中是否已经有A表中新插入的数据行,如果没有,则也插入
51
IF
NOT
EXISTS
(
SELECT
TOP
1
1
FROM
c,inserted i
where
c.a1
=
i.a1
and
c.b1
=
i.b1
and
c.c1
=
i.c1)
52
insert
into
c
select
*
from
inserted
53
END
54
IF
@DML
=
2
55
BEGIN
56
--
检查B表中是否有A表中更新前的这行数据,如果有,则不需要更新C表中的数据,而是要把A表中更新后的这行数据插入到C表中
57
IF
NOT
EXISTS
(
SELECT
TOP
1
1
FROM
B,DELETED d
where
b.a1
=
d.a1
and
b.b1
=
d.b1
and
b.c1
=
d.c1)
58
BEGIN
59
--
如果C表中不存在A表更新后的这行数据,则更新C表中跟A表更新前那行数据相同的数据
60
IF
NOT
EXISTS
(
SELECT
TOP
1
1
FROM
C,INSERTED I
WHERE
C.A1
=
I.A1
AND
C.B1
=
I.B1
AND
C.C1
=
I.C1)
61
BEGIN
62
UPDATE
C
SET
A1
=
I.A1,B1
=
I.B1,C1
=
I.C1
FROM
C,INSERTED I,DELETED D
WHERE
C.A1
=
D.A1
AND
C.B1
=
D.B1
AND
C.C1
=
D.C1
63
END
64
--
如果C表中存在A表更新后的这行数据,则需要删除C表中跟A表更新前相同的那行数据
65
ELSE
66
BEGIN
67
SELECT
@A1_D
=
A1,
@B1_D
=
B1,
@C1_D
=
C1
FROM
DELETED
68
DELETE
FROM
C
WHERE
@A1_D
=
A1
AND
@B1_D
=
B1
AND
@C1_D
=
C1
69
END
70
END
71
ELSE
72
insert
into
c
select
*
from
inserted i
where
not
exists
(
select
1
from
c
where
i.a1
=
c.a1
and
i.b1
=
c.b1
and
i.c1
=
c.c1)
73
END
74
IF
@DML
=
3
75
BEGIN
76
--
如果B表中不存在A表要删除的这行数据,则需要从C表中删除这行数据
77
IF
not
exists
(
select
top
1
1
from
b,deleted d
where
b.a1
=
d.a1
and
b.b1
=
d.b1
and
b.c1
=
d.c1)
78
DELETE
FROM
C
WHERE
EXISTS
(
SELECT
1
FROM
deleted d
where
c.a1
=
d.a1
and
c.b1
=
d.b1
and
c.c1
=
d.c1)
79
END
80
EXIT_:
81
82
CREATE
TRIGGER
SYNC_C_BY_B
83
ON
B
84
AFTER
INSERT
,
UPDATE
,
DELETE
85
AS
86
Declare
@Dml
TinyInt
--
1:Insert 2:Update 3:Delete
87
Declare
@RowsD
Int
88
Declare
@RowsI
Int
89
Declare
@A1_D
nvarchar
(
10
)
90
Declare
@B1_D
Nvarchar
(
10
)
91
Declare
@C1_D
Nvarchar
(
10
)
92
--
确定是哪一种dml操作
93
Select
@RowsD
=
Count
(
*
)
From
Deleted
94
Select
@RowsI
=
Count
(
*
)
From
Inserted
95
If
@RowsD
=
0
And
@RowsI
=
0
96
Goto
Exit_
97
If
@RowsD
=
0
And
@RowsI
>
0
98
Set
@Dml
=
1
99
Else
100
If
@RowsD
>
0
And
@RowsI
>
0
101
Set
@Dml
=
2
102
Else
103
If
@RowsD
>
0
And
@RowsI
=
0
104
Set
@Dml
=
3
105
IF
@DML
=
1
106
BEGIN
107
--
检查c表中是否已经有B表中新插入的数据行,如果没有,则也插入
108
IF
NOT
EXISTS
(
SELECT
TOP
1
1
FROM
c,inserted i
where
c.a1
=
i.a1
and
c.b1
=
i.b1
and
c.c1
=
i.c1)
109
insert
into
c
select
*
from
inserted
110
END
111
IF
@DML
=
2
112
BEGIN
113
--
检查B表中是否有A表中更新前的这行数据,如果有,则不需要更新C表中的数据,而是要把A表中更新后的这行数据插入到C表中
114
IF
NOT
EXISTS
(
SELECT
TOP
1
1
FROM
A,DELETED d
where
a.a1
=
d.a1
and
a.b1
=
d.b1
and
a.c1
=
d.c1)
115
BEGIN
116
--
如果C表中不存在B表更新后的这行数据,则更新C表中跟b表更新前那行数据相同的数据
117
IF
NOT
EXISTS
(
SELECT
TOP
1
1
FROM
C,INSERTED I
WHERE
C.A1
=
I.A1
AND
C.B1
=
I.B1
AND
C.C1
=
I.C1)
118
BEGIN
119
UPDATE
C
SET
A1
=
I.A1,B1
=
I.B1,C1
=
I.C1
FROM
C,INSERTED I,DELETED D
WHERE
C.A1
=
D.A1
AND
C.B1
=
D.B1
AND
C.C1
=
D.C1
120
END
121
--
如果C表中存在更新B表后的这行数据,则需要删除C表中跟B表更新前相同的那行数据
122
ELSE
123
BEGIN
124
SELECT
@A1_D
=
A1,
@B1_D
=
B1,
@C1_D
=
C1
FROM
DELETED
125
DELETE
FROM
C
WHERE
@A1_D
=
A1
AND
@B1_D
=
B1
AND
@C1_D
=
C1
126
End
127
128
END
129
ELSE
130
insert
into
c
select
*
from
inserted i
where
not
exists
(
select
1
from
c
where
i.a1
=
c.a1
and
i.b1
=
c.b1
and
i.c1
=
c.c1)
131
END
132
IF
@DML
=
3
133
BEGIN
134
--
如果A表中不存在B表要删除的这行数据,则需要从C表中删除这行数据
135
if
not
exists
(
select
top
1
1
from
a,deleted d
where
a.a1
=
d.a1
and
a.b1
=
d.b1
and
a.c1
=
d.c1)
136
DELETE
FROM
C
WHERE
EXISTS
(
SELECT
1
FROM
deleted d
where
c.a1
=
d.a1
and
c.b1
=
d.b1
and
c.c1
=
d.c1)
137
END
138
EXIT_: