1

我们的 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 发布过程中维护这种可自定义的字段?

4

2 回答 2

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

请注意,通过这样做,您将无法对dbo.FormatAccountNumberSSDT 数据库项目中的函数进行任何引用(除非这些对象也包含在 Post-Deployment 脚本中)。

我还玩弄了一个替代解决方案,该解决方案涉及.sqlproj文件本身(在ItemGroup元素内)中的附加条件,但这确实有点混乱,因为 MsBuild 属性与 SQLCMD 变量并不完全一样,但如果我可以发布这个你喜欢。

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

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

于 2012-09-26T03:07:13.047 回答
0

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

于 2013-07-27T02:25:52.427 回答