Ruby on rails 如何从Rails中的外部数据库同步数据?
我正在将另一个数据库中的信息导入Rails数据库。目前,我已经查询了数据库以从表中获取所有记录,然后创建了模型的新对象并分配了值。我想检测一条记录是否已更新,如果已更新,我将更新该记录。这些记录大约有40个属性。我可以使用什么方法查询数据库以查看记录是否已更改?目前我正在使用以下方法,但速度似乎很慢Ruby on rails 如何从Rails中的外部数据库同步数据?,ruby-on-rails,sql-server,rails-activerecord,Ruby On Rails,Sql Server,Rails Activerecord,我正在将另一个数据库中的信息导入Rails数据库。目前,我已经查询了数据库以从表中获取所有记录,然后创建了模型的新对象并分配了值。我想检测一条记录是否已更新,如果已更新,我将更新该记录。这些记录大约有40个属性。我可以使用什么方法查询数据库以查看记录是否已更改?目前我正在使用以下方法,但速度似乎很慢 SELECT A.attribute1, A.attribute2, A.attribute3, ... FROM external.dbo.myobject A INNER JOIN int
SELECT A.attribute1, A.attribute2, A.attribute3, ...
FROM external.dbo.myobject A
INNER JOIN internal.dbo.myobject B
ON A.key = B.key
WHERE (A.attribute1 <> B.attribute1 OR
A.attribute2 <> B.attribute2 OR
A.attribute3 <> B.attribute3 OR
...)
1要检测更改,最简单的解决方案是使用 上述质询/声明
INSERT INTO #changes (...)
SELECT ... FROM external.dbo.object
EXCEPT
SELECT ... FROM internal.dbo.object
将external.dbo.object中不同或不存在于internal.dbo.object中的所有行插入到更改中
对于sync,我将使用语句,请参见上面的示例:
MERGE dbo.InternalObj AS i
USING #changes AS e ON i.ID = e.ID
WHEN MATCHED
THEN UPDATE SET ...
WHEN NOT MATCHED
THEN INSERT ... -- This clause INSERT new rows
2检测更改的另一个选项是使用数据类型,它是插入或更新行时自动生成的二进制值
例如:
CREATE TABLE dbo.InternalObj (
ID INT PRIMARY KEY,
ColA VARCHAR(100) NOT NULL,
rw BINARY(8) NOT NULL
);
GO
CREATE TABLE dbo.ExternalObj (
ID INT IDENTITY(1,1) PRIMARY KEY,
ColA VARCHAR(100) NOT NULL,
rw ROWVERSION NOT NULL -- When ColA values are changed, SQL Server will automaticcaly update [rw]
);
GO
INSERT dbo.ExternalObj (ColA) VALUES ('A')
INSERT dbo.ExternalObj (ColA) VALUES ('B')
GO
-- First test & sync
MERGE dbo.InternalObj AS i
USING dbo.ExternalObj AS e ON i.ID = e.ID
WHEN MATCHED AND i.rw <> e.rw -- Same [ID] but differet [rw] values
THEN
UPDATE -- This clause update changed rows
SET i.ColA = e.ColA,
i.rw = e.rw
WHEN NOT MATCHED
THEN
INSERT (ID, ColA, rw) -- This clause INSERT new rows
VALUES (e.ID, e.ColA, e.rw);
GO
SELECT * FROM dbo.InternalObj;
/*
ID ColA rw
----------- ---- ------------------
1 A 0x0000000000000FA6
2 B 0x0000000000000FA7
*/
GO
-- Second test & sync
INSERT dbo.ExternalObj (ColA) VALUES ('C')
UPDATE dbo.ExternalObj
SET ColA = ColA + '#'
WHERE ID = 2
GO
MERGE dbo.InternalObj AS i
USING dbo.ExternalObj AS e ON i.ID = e.ID
WHEN MATCHED AND i.rw <> e.rw -- Same [ID] but differet [rw] values
THEN
UPDATE -- This clause update changed rows
SET i.ColA = e.ColA,
i.rw = e.rw
WHEN NOT MATCHED
THEN
INSERT (ID, ColA, rw) -- This clause INSERT new rows
VALUES (e.ID, e.ColA, e.rw);
GO
SELECT * FROM dbo.InternalObj;
/*
ID ColA rw
----------- ---- ------------------
1 A 0x0000000000000FA6
2 B# 0x0000000000000FA9
3 C 0x0000000000000FA8
*/
GO
注意:二进制校验和函数可能会生成具有不同值的哈希冲突行=>相同校验和=>未检测到更改。您能提供更多信息吗?例如,内部行被复制到外部数据库中,这些外部行被更新其中一些,然后您必须只检测更新的行吗?当同一行的同一ID/PK值在两侧更新时会发生什么情况:外部和内部?有更多的外部数据库,或者计划使用两个或更多的外部数据库?@BogdanSahlean,我很抱歉。目前,内部数据库将不会被编辑,因为所有编辑都将在我从中导入记录的外部数据库中进行。我将只是从内部数据库中读取。因此,我能看到的唯一检查是查看外部数据库记录是否具有与内部数据库不同的属性。如果是,则更新内部记录以匹配外部记录。我不需要检查反面。谢谢
ALTER TABLE dbo.InternalObj DROP COLUMN [rw]
ALTER TABLE dbo.ExternalObj DROP COLUMN [rw]
GO
-- Test / sync
;WITH CteTarget
AS (
SELECT *, BINARY_CHECKSUM(*) AS CRC
FROM (
SELECT ID, ColA -- Only selected columns
FROM dbo.InternalObj
) x
), CteSource
AS (
SELECT *, BINARY_CHECKSUM(*) AS CRC
FROM (
SELECT ID, ColA -- Only selected columns
FROM dbo.ExternalObj
) y
)
MERGE CteTarget i
USING CteSource e ON i.ID = e.ID
WHEN MATCHED AND EXISTS(SELECT i.CRC EXCEPT SELECT e.CRC) -- Same [ID] but differet [CRC] values
THEN
UPDATE -- This clause update changed rows
SET i.ColA = e.ColA
WHEN NOT MATCHED
THEN
INSERT (ID, ColA) -- This clause INSERT new rows
VALUES (e.ID, e.ColA);
GO
SELECT * FROM dbo.InternalObj;
/*
ID ColA
----------- ----
1 A
2 B
*/
GO