如何在Azure SQL DB服务器中动态合并多库同结构表至单一目标库
问题描述
我有98个数据库,每个数据库包含352张表,所有数据库的表结构完全一致。需要将所有数据库中对应表的数据动态追加到单一目标数据库merged_db中。以下是我编写的存储过程代码:
CREATE or ALTER PROCEDURE AppendTablesDynamically AS BEGIN SET NOCOUNT ON; DECLARE @TableName NVARCHAR(max),@DatabaseName NVARCHAR(max),@SQL NVARCHAR(MAX) -- loop through all the tables in all the databases DECLARE curTables CURSOR FOR SELECT TABLE_NAME AS TableName,TABLE_CATALOG AS DatabaseName FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' OPEN curTables FETCH NEXT FROM curTables INTO @TableName, @DatabaseName WHILE @@FETCH_STATUS = 0 BEGIN -- build the SQL statement to append the table SET @SQL ='use' 'SELECT * into '+'merged_db.dbo.new_' +@TableName+ ' FROM '+ @TableName -- execute the SQL statement EXEC sp_executesql @SQL FETCH NEXT FROM curTables INTO @TableName, @DatabaseName END CLOSE curTables DEALLOCATE curTables END EXEC AppendTablesDynamically
代码问题分析及修正
原存储过程存在多处语法和逻辑错误,无法实现需求,以下是修正后的版本及关键说明:
修正后的存储过程
CREATE OR ALTER PROCEDURE AppendTablesDynamically AS BEGIN SET NOCOUNT ON; DECLARE @TableName NVARCHAR(128), @DatabaseName NVARCHAR(128), @SQL NVARCHAR(MAX); -- 遍历所有数据库中的所有基表,排除目标数据库避免重复导入 DECLARE curTables CURSOR FOR SELECT TABLE_NAME AS TableName, TABLE_CATALOG AS DatabaseName FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG <> 'merged_db'; OPEN curTables; FETCH NEXT FROM curTables INTO @TableName, @DatabaseName; WHILE @@FETCH_STATUS = 0 BEGIN -- 先判断目标表是否存在,不存在则创建,存在则追加数据 -- 用QUOTENAME包裹对象名,避免特殊字符引发语法错误 SET @SQL = N' IF NOT EXISTS (SELECT 1 FROM merged_db.sys.tables WHERE name = N''new_' + @TableName + ''') BEGIN SELECT * INTO merged_db.dbo.new_' + QUOTENAME(@TableName) + ' FROM ' + QUOTENAME(@DatabaseName) + '.dbo.' + QUOTENAME(@TableName) + ' END ELSE BEGIN INSERT INTO merged_db.dbo.new_' + QUOTENAME(@TableName) + ' SELECT * FROM ' + QUOTENAME(@DatabaseName) + '.dbo.' + QUOTENAME(@TableName) + ' END'; EXEC sp_executesql @SQL; FETCH NEXT FROM curTables INTO @TableName, @DatabaseName; END CLOSE curTables; DEALLOCATE curTables; END GO EXEC AppendTablesDynamically;
关键修正点说明
- 修复语法错误:原代码中
'use' 'SELECT * into'拼接完全错误,修正后直接使用数据库名.架构.表名的完整对象路径,无需切换数据库上下文 - 替换数据写入逻辑:
SELECT INTO仅能创建新表一次,后续执行会触发“表已存在”错误;修正后先判断目标表是否存在,不存在则创建,存在则执行INSERT INTO追加数据 - 添加源数据库引用:原代码未指定源数据库,导致只会读取当前数据库的表数据;修正后通过
@DatabaseName拼接完整源表路径,确保从对应数据库读取数据 - 处理特殊字符:用
QUOTENAME包裹数据库名和表名,避免名称含空格、特殊字符或关键字时引发语法错误 - 排除目标库:在游标查询中添加过滤条件,避免将目标库自身的数据重复导入
内容的提问来源于stack exchange,提问作者Ariharan Ramaraj
相关产品推荐
相关产品推荐

