我正在处理 SQL Server 2008 中的一种情况,其中每个客户端都设置为自己的数据库,每个数据库都具有相同的表结构。
我有一个查询,它从数据库中的 ~20 个不同表中进行选择,并将记录插入到报告数据库中。我们想要做的是对每个数据库重复此过程,以便跨所有客户端数据库的所有报告信息都包含在统一报告数据库中。
“简单”的方法是只复制/粘贴代码并在数据库名称上查找/替换所有内容,以使脚本在所有客户端上执行。还有比这更好的方法吗?
这个答案假设您有一个主数据库/客户表及其关联的数据库名称,或者某种方式来确定给定 SQL Server 实例中的哪些数据库具有您想要查询的相关数据库。
由于这是出于报告目的,您可能希望实施某种形式的快照技术,以确保数据集至少在每个客户端的基础上合并到同一时间点。作为一个很好的副作用,这些技术通常还可以减轻直接针对生产数据运行这些类型的查询的锁定/阻塞影响。
纯动态 SQL
使用主列表构建一个 SQL 语句,该语句使用由 3 部分组成的名称,就像您现在所做的那样,而是动态注入数据库名称。从问题中不清楚数据最终会采用什么格式,但听起来您想要将UNION ALL
所有内容放在一起,这很容易实现。
这对您现在可能是有利的,因为它只需要很少的前期工作。
缺点是这种方法不是很灵活,并且如果您需要在各个数据库修订版本不同时运行查询(即,查询与给定的数据库修订版本相关,并且在部署数据库更新时,它会很快变得复杂)并非对所有客户都成功)。根据您为这些数据库使用的安全模型,它也可能存在问题或并发症。
基于数据库的对象 + 动态 SQL
此解决方案在每个数据库中创建永久对象,您可以在外部进程中查询这些对象。通常这意味着视图、存储过程或表值函数。如上所述,动态 SQL 将用于将数据库名称注入到查询中,但这次所需要的只是从数据库对象中选择或执行数据库对象,而不是直接执行原始查询。
这种方法提供了保护接口后面代码的所有优点,就像在应用程序代码中使用视图、存储过程等一样。这也更容易解决安全问题。
当然,缺点是这需要更多的前期工作和管理,并且查询对象只能在数据库更新中部署,而不是独立部署。
我个人的意见是后一种方法是更好的长期解决方案,因此在这种情况下,我会选择这种方法。对于临时类型的查询,使用纯动态 SQL 方法就可以了。