SSDT项目中模式对象的条件编译

时间:2012-09-25 19:20:28

标签: conditional-compilation sql-server-data-tools

我们的SSDT数据库项目包括一个具有计算列的表,该列可以根据客户要求采用多种形式之一。我正在试图弄清楚如何管理这个计算列,这样我们仍然可以使用Publish功能,而不会将每个人的列恢复为默认值。

我想要完成的内容可以在以下 无效 T-SQL代码中解释:

CREATE TABLE dbo.Customer
(
  Id INTEGER,
  Region INTEGER,
  Name VARCHAR(50),
  AccountNumber AS dbo.FormatAccountNumber(Id, Region)
)

CREATE FUNCTION [dbo].[FormatAccountNumber]
(
  @Id INTEGER,
  @Region INTEGER
)
RETURNS VARCHAR(20)
AS
BEGIN
  IF '$(AccountType)' = 'Regional'
    RETURN CONVERT(VARCHAR, @Region) + '-' + CONVERT(VARCHAR, @Id)

  IF '$(AccountType)' = 'Merged'
    RETURN CONVERT(VARCHAR, @Region * 100000 + @Id)

  IF '$(AccountType)' = 'Flat'
    RETURN CONVERT(VARCHAR, @Id)
END

当然,这不起作用,因为$(AccountType) SQLCMD变量不能在函数内部使用,并且无论如何都不会在运行时正确设置。我也尝试将SQLCMD条件化为整个函数:

IF '$(AccountType)' = 'Flat'
  CREATE FUNCTION ...

但是这会产生错误“CREATE FUNCTION必须是批处理中的唯一语句。”

有没有办法在SSDT项目中进行任何类型的模式条件编译?如果没有,我在SSDT发布过程中有哪些选项来维护这种可自定义的字段?

2 个答案:

答案 0 :(得分:2)

您可以使用Post-Deploment脚本在动态SQL中强制部署对象:

IF NOT EXISTS (SELECT * FROM sys.objects 
            WHERE object_id = OBJECT_ID(N'[dbo].[FormatAccountNumber]') 
            AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
EXEC('CREATE FUNCTION [dbo].[FormatAccountNumber] () RETURNS BIT AS BEGIN RETURN 0 END')
GO 

IF '$(AccountType)' = 'Regional'
BEGIN
    EXEC('
        ALTER FUNCTION [dbo].[FormatAccountNumber]
        (
          @Id INTEGER,
          @Region INTEGER
        )
        RETURNS VARCHAR(20)
        AS
        BEGIN
            RETURN CONVERT(VARCHAR, @Region) + ''-'' + CONVERT(VARCHAR, @Id)
        END
    ')
END

请注意,通过执行此操作,您将无法对SSDT数据库项目中的dbo.FormatAccountNumber函数进行任何引用(除非这些对象也包含在部署后脚本中)。

我还玩了一个替代解决方案,其中涉及.sqlproj文件本身内的附加条件(在ItemGroup元素内),但由于MsBuild Properties不完全像 - 所以这确实有点混乱与SQLCMD变量类似,但如果你愿意,我可以发布这个。

如果您发现自己需要经常在数据库中有条件地部署对象,您可能会考虑转向基于命令式的部署解决方案(而不是SSDT项目的声明式)。命令式部署(通常称为迁移)使您可以更好地控制部署时行为。

免责声明:我是ReadyRoll的创始人,ReadyRoll为使用命令式部署的VS制作产品。

答案 1 :(得分:0)

我在MSDN上就此需求进行了公开讨论。没有取得多大进展。理想情况允许您在基本ssdt项目中将db对象标记为“可继承”,以便引用基础项目或DAC的其他项目不会抱怨重复对象,并且只会创建基础对象或“存根”它不存在。这将允许您拥有数据库模型的“层”。请参阅msdn Extending SSDT Composite Solutions with Overriden Stored Procedures

上的帖子