我知道,实现这一点的最佳方法可能是对应用程序代码进行一些更改,以将所有更改保存在两个表中,但公司命令使用触发器对数据库逻辑进行更改。因此,有两个不同的数据库,都有一个名为User的表,而且它们已经有了相同的模型。我在数据库X上的User中插入/更新的内容必须插入/更新在数据库Y上的User表中,反之亦然。
我设法使插入和更新触发器指向一个方向(数据库X->数据库Y(,但现在我想,当我在数据库Y上创建触发器时,会发生循环。缺少什么,或者我能做些什么来使触发循环不发生?这是我目前在其中一个数据库上创建的:
---insert trigger
USE [DATABASE_Y]
CREATE TRIGGER [dbo].[TR_USER_OnInsert] ON [dbo].[USER]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
INSERT INTO [DATABASE_X].[dbo].[USER] (
usu_id,
usu_name,
usu_block,
usu_login,
usu_password
)
SELECT
usu_id,
usu_name,
usu_block,
usu_login,
usu_password
FROM INSERTED
SET NOCOUNT OFF
END
---update trigger
USE [DATABASE_Y]
ALTER TRIGGER [dbo].[TR_USER_OnUpdate] ON [dbo].[USER]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON
UPDATE X
SET
X.usu_id = INSERTED.usu_id,
X.usu_name = INSERTED.usu_name,
X.usu_block = INSERTED.usu_block,
X.usu_login = INSERTED.usu_login,
X.usu_password = INSERTED.usu_password
FROM [DATABASE_X].[dbo].[USER] X
INNER JOIN inserted ON X.usu_login = inserted.usu_login
SET NOCOUNT OFF
END
有趣的方法。有很多不同的方法可以解决这个问题,其中大多数都比使用触发器更好。
也就是说。。。
作为触发代码的一部分,在内存中创建一些变量,然后在运行更新/插入之前对目标数据库运行select以填充它们。使用一些简单的逻辑来检查这些值是否已经设置为相同的值,并避免进入循环。
类似这样的更新触发器:
USE [DATABASE_Y]
ALTER TRIGGER [dbo].[TR_USER_OnUpdate] ON [dbo].[USER]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE @id as varchar(100)
DECLARE @name as varchar(100)
DECLARE @block as varchar(100)
DECLARE @login as varchar(100)
DECLARE @password as varchar(100)
SELECT @id = X.usu_id,
@name = X.usu_name,
@block = X.usu_block,
@login = X.usu_login,
@password = X.usu_password
FROM [DATABASE_X].[dbo].[USER] X
WHERE X.usu_login = inserted.usu_login
IF @id <> INSERTED.usu_id
OR @name <> INSERTED.usu_name
OR @block <> INSERTED.usu_block
OR @login <> INSERTED.usu_login
OR @password <> INSERTED.usu_password
BEGIN
UPDATE X
SET
X.usu_id = INSERTED.usu_id,
X.usu_name = INSERTED.usu_name,
X.usu_block = INSERTED.usu_block,
X.usu_login = INSERTED.usu_login,
X.usu_password = INSERTED.usu_password
FROM [DATABASE_X].[dbo].[USER] X
INNER JOIN inserted ON X.usu_login = inserted.usu_login
END
SET NOCOUNT OFF
END
我不知道你的数据类型是什么,所以我只是假设varchar(100(代表所有数据。
请确保所有列都不是NULL。如果有任何可为null的列,请确保将ISNULL逻辑添加到变量比较中。
插入触发器稍微简单一点,因为您只需要检查您试图插入的userId是否已经存在:
USE [DATABASE_Y]
CREATE TRIGGER [dbo].[TR_USER_OnInsert] ON [dbo].[USER]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
IF NOT EXISTS(SELECT 1 FROM [DATABASE_X].[dbo].[USER] WHERE usu_login = INSERTED.usu_login)
BEGIN
INSERT INTO [DATABASE_X].[dbo].[USER] (
usu_id,
usu_name,
usu_block,
usu_login,
usu_password
)
SELECT
usu_id,
usu_name,
usu_block,
usu_login,
usu_password
FROM INSERTED
END
SET NOCOUNT OFF
END