基于表/列存在的存储过程逻辑

时间:2014-03-28 14:25:44

标签: sql-server sp-executesql

我有一大堆存储过程可以复制我们正在处理的各种环境中的实体(跨越30多个表): Dev / Integration / PreProd / Prod

这个想法有时候数据库结构会从平台变为另一个平台。一般情况下,我们会进行一些小的更改,例如将1-2列移动到新表或向结构中添加新表等。

考虑到此复制的复杂性,我希望在所有环境中都有这些过程的单个版本,无论与DB结构有何不同,都可以从任何环境到另一个环境进行复制。例如,如果列存在于 src dest =>做那个逻辑,否则做其他逻辑等。

我的想法是,即使代码检查列存在,也不能在存储过程中使用存在的列,并且永远不会执行该代码分支。

最好找到的选项是使用sp_executesql编写代码,但代码变得非常复杂:考虑到我在结构更改后必须丢弃部分代码在所有环境中都是一致的。

1 个答案:

答案 0 :(得分:2)

我会确保您需要的所有表和所有将来的表都具有可识别的命名约定,因此您可以使用sys.all_objects和sys.all_columns表查询要复制的表/列。在此示例中,您可以通过@SourceDB参数将源数据库名称传递给存储过程,并执行源/目标表/列名称相交的插入。未指定目标数据库,因为它被假定为当前数据库:

-- get intersecting table/column names from @SourceDB
-- and Destination (Current) DB
declare @sql nvarchar(max)
set @sql = 'select o.name,c.name
    from ' + @SourceDB + '.sys.all_objects o
        inner join ' + @SourceDB + '.sys.all_columns c
            on c.object_id = o.object_id
    where o.type = ''U''
    and o.name like ''SomeStringToIdentifyYourTables%''
    intersect
    select o.name,c.name
    from sys.all_objects o
        inner join sys.all_columns c
            on c.object_id = o.object_id
    where o.type = ''U''
    and o.name like ''SomeStringToIdentifyYourTables%'''   
declare @TblColNames table(TblName nvarchar(200),ColName nvarchar(200))
insert into @TblColNames
exec(@sql)

-- insert data from Source DB to Destination (Current) DB
-- where Table/Column Names Intersect
declare @sql nvarchar(max)
set @sql = ''
select @sql = @sql + 'insert into ' +
    o.name + ' (' + replace((
                    select c.name +
                        case row_number() over(order by c.name desc)
                        when 1 then '' else '||' end
                    from @TblColNames c
                    where c.TblName = o.TblName
                    order by c.name asc
                    for xml path('')),'||',',') + ')
    select ' + replace((
                    select c.name +
                        case row_number() over(order by c.name desc)
                        when 1 then '' else '||' end
                    from @TblColNames c
                    where c.TblName = o.TblName
                    order by c.name asc
                    for xml path('')),'||',',') + '
    from ' + @SourceDB + '..' + o.name + '
'
from @TblColNames o
exec(@sql)