2012-09-25 46 views
1

我們的SSDT數據庫項目包含一個表,其中包含一個計算列,可根據客戶要求採用多種形式之一。我試圖弄清楚如何管理這個計算列,以便我們仍然可以使用發佈功能而不需要將所有人的列都還原爲默認值。SSDT項目中的模式對象的條件編譯

我試圖完成可以通過以下無效 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

你可以使用後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.FormatAccountNumber功能的任何引用您的SSDT數據庫項目(除非這些對象也包含在部署後腳本中)。

我還玩過一個替代解決方案,它涉及.sqlproj文件本身(在ItemGroup元素內)中的附加條件,但是這確實有點混亂,因爲構建屬性與SQLCMD變量不完全相似,但如果你喜歡,我可以發表。

如果您發現自己需要經常在數據庫中有條件地部署對象,那麼您可能會考慮轉向基於命令式的部署解決方案(而不是SSDT項目的聲明式樣式)。勢在必行的部署(通常稱爲遷移)使您可以更好地控制部署時間行爲。

免責聲明:我是ReadyRoll的創始人,它爲使用命令性部署的VS製作產品。

+0

這是我們所傾向的解決方案,但是這不會迫使我們在每個部署中都刪除並重新創建該功能,即使這些功能沒有改變?我們最感興趣的部分SSDT項目是自動生成的「sql diff」部署腳本。 –

+0

的確如此。我已將上述SQL修改爲僅在每個部署中使用ALTER對象。它不會給你完全相同的結果(例如,sql diff部署),但至少不需要每次都刪除它。 –

+2

我想我會將條件中的SQL重構爲自己的腳本文件,並讓部署後腳本調用該文件。 –

0

我已經在MSDN上公開討論過這個需求。沒有取得太大的進展。理想的情況是,您可以在基本ssdt項目中將db對象標記爲「可繼承」,以便引用基礎項目或DAC的其他項目不會抱怨重複的對象,並且只會創建基礎對象或「存根」if它不存在。這將允許您擁有數據庫模型的「圖層」。在msdn上查看我的帖子Extending SSDT Composite Solutions with Overriden Stored Procedures