我需要快速实现一个只读数据库,其中包含从两个结构相同的实时数据库中提取的数据。
实时数据库实际上是来自 Dynamics 会计系统的公司数据库,所以我很高兴有任何 Dynamics 特定的建议,但这主要是一个 SQL 问题。这是微软收购 Great Plains 之前相当老的 Dynamics 版本。这是在 SQL Server 2000 上。
我们有访问动态数据的报告和应用程序。这些应用程序旨在查看一个公司数据库。现在我们需要添加另一个。这些报告和应用程序中的大多数都可以看到组合数据。他们并不真正关心订单或发票存在于哪家公司。他们只查看少数表格。
在我看来,最简单的解决方案是创建一个仅包含合并数据的报告数据库。最好,我们需要一种有效的方法来每天多次更新这个数据库。
我是开发人员,不是数据库专家,但这是我的计划:
最初使用与实时数据库相同的表结构创建具有所需表的组合报告数据库。
所有 Dynamics 表似乎都有一个名为 DEX_ROW_ID 的 int 标识列。我不确定它的用途,(它没有被索引)但这似乎是唯一标识行的明显通用方法。在报告数据库上,我会将其更改为正常的 int(不是身份)。我将在所有数据库中的 DEX_ROW_ID 上创建一个唯一索引。
Dynamics 没有时间戳,因此我将在实时数据库中的表中添加时间戳列,并在报告数据库中添加相应的 binary(8) 列。我假设并希望 Dynamics 不会因额外的索引和列而感到不安。
将 int CompanyId 列添加到报告数据库表中,并将其添加到任何唯一索引的末尾。即使没有它,大多数数据自然也是独一无二的。即,两个实时数据库的订单和发票号码等将不同。我们可能需要对应用程序进行一些小的更改,但除了将它们指向新的报告数据库之外,我不希望做太多事情。
假设我的报告数据库称为 Reports,实时数据库是 Live1 和 Live2,时间戳列称为 TS,所有数据库都在同一台服务器上……这是我第一次尝试更新脚本,用于在一个名为 MyTable 的表中复制更改在 Live1 到报告数据库。
USE Reports
CREATE TABLE #Changes
(
ReportId int,
LiveId int
)
/* Collect in a temp table the ids or rows which have been deleted or changed
in the live db L.DEX_ROW_ID will be null if the row has been deleted */
INSERT INTO #Changes
SELECT R.DEX_ROW_ID, L.DEX_ROW_ID
FROM MyTable R LEFT OUTER JOIN Live1.dbo.MyTable L ON L.DEX_ROW_ID = R.DEX_ROW_ID
WHERE R.CompanyId = 1 AND L.DEX_ROW_ID IS NULL OR L.TS <> R.TS
/* Delete rows that have been deleted or changed on the live db
I wonder if using join syntax would run better than the subquery. */
DELETE FROM MyTable
WHERE CompanyId = 1 AND DEX_ROW_ID IN (SELECT ReportId FROM #Changes)
/* Recopy rows that have changed in the live db */
INSERT INTO MyTable
SELECT 1 AS CompanyId, * FROM Live1.dbo.MyTable L
WHERE L.DEX_ROW_ID IN (SELECT ReportId FROM #Changes WHERE LiveId IS NOT NULL)
/* Copy the rows that are new in the live db */
INSERT INTO MyTable
SELECT 1 AS CompanyId, * FROM Live1.dbo.MyTable
WHERE DEX_ROW_ID > (SELECT MAX(DEX_ROW_ID) FROM MyTable WHERE CompanyId = 1)
然后对 Live2 数据库执行相同的操作。对报告中的每个表重复此操作。我知道我应该使用参数@CompanyId 而不是文字,但我不能为实时数据库名称这样做,有些我可能会使用 C# 程序或其他东西动态生成这些名称。
我正在寻找任何关于我在这里所做的事情的建议、建议或批评。我知道它不会是原子的。此脚本运行时,实时数据库上可能会发生一些事情。我认为我们可以忍受这一点。当实时数据库上没有发生任何事情时,我们可能会每晚或每周进行一次完整复制。
我们需要注重性能而不是优雅或完美。一些初始测试有第一个查询,其中最大表的 TS 比较运行时间约为 30 秒,所以我很乐观这会起作用,但我也想知道我是否遗漏了一些明显的东西或没有看到以树为林。
我们真的不想处理报告数据库上的日志文件。我们可以将其设置为简单的恢复模式而忘记日志吗?
谢谢