【问题标题】:Stored procedure logic based on table/column existence基于表/列存在的存储过程逻辑
【发布时间】:2014-03-28 14:25:44
【问题描述】:

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

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

考虑到这种复制的复杂性,我希望在所有环境中都有这些程序的单一版本,无论与数据库结构相关的差异如何,以便可以从任何环境复制到另一个环境。例如,如果列存在于 srcdest => 做那个逻辑,否则做其他逻辑,等等。

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

找到的最佳选择是使用sp_executesql 编写代码,但代码变得非常复杂:考虑到太多了,一旦结构更改全部对齐,我将不得不丢弃部分代码环境。

【问题讨论】:

  • 我认为我们在这里混淆了“迁移”工作。对于大多数人来说,这意味着从架构的一个版本转移到下一个版本(添加/删除列和表,更新存储过程等)。您似乎用它来表示“复制”:将数据从一台服务器复制到另一台服务器。你能澄清一下吗?
  • @TimRogers: 只是把这个词改成了“复制”,希望不会干扰 SQL Server 的复制机制。
  • 如果你提供一些合理的例子,我会更容易理解。也许一个例子改变了一个前后精简的存储过程。事实上,它还不够具体。
  • @KarlKieninger:假设您有一个“房屋计划”存储在数据库的大约 30 个表中(一个用于房屋结构的表格,一个用于调色板的表格等)。一旦 DEV 团队完成它的工作,计划屋就会在集成方面“提升”,其中还存在由设计师开发的良好图像/调色板。当一切正常后,它会进入 PRE-PROD,向客户显示“房屋计划”,并对不同的属性进行一些小的更改(例如更改调色板中的颜色等)。 SP 是这样的:usp_CopyDataFromTableA、usp_CopyDataFromTableB 等

标签: sql-server sp-executesql


【解决方案1】:

我会确保您需要的所有表和所有未来的表都具有可识别的命名约定,以便您可以使用 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)

【讨论】:

  • 好主意,即使它不适合帖子。
  • 这篇文章怎么不适合?是否有您未提及的内容阻止了您的问题的解决?
猜你喜欢
  • 2013-04-05
  • 1970-01-01
  • 2011-11-04
  • 2011-05-28
  • 2022-01-06
  • 1970-01-01
  • 2017-03-07
  • 1970-01-01
  • 2012-01-22
相关资源
最近更新 更多