2014-03-27 83 views
1

我最近需要在應用程序的MSSQL後端上使用SMO運行創建表格和更新表格腳本,並發現(不奇怪)您不能簡單地就像使用存儲過程一樣,用ALTER TABLE替換CREATE TABLE語句...如何使用SMO從「創建腳本」創建「表格變更」腳本

因此,我通過更改表格並在表格上簡單選擇「生成更改腳本」來了解SSMS如何實現它。然後,我使用這個更改腳本來確定我的函數需要什麼,以便使其更通用,並使用CREATE TABLE腳本文件中的整個表列表進行新安裝。

對於任何感興趣的人,下面的答案是我的函數(在VB.NET中)使用SMO。它並不完美,但我希望如果不能解決同樣的問題,你會發現它是一個很好的起點。

+0

是這裏有個問題嗎? –

+0

不 - 它是一個我希望人們會覺得有用的帖子 – R144N

回答

1

我的例子假設:

  • ,你必須使用SMO已連接到服務器和本地數據庫和分配的本地數據庫的「dbLocal」變量。
  • 您的項目包含一個SQL腳本文件,用CREATE TABLE語句(傳遞給函數的字符串參數)

(我已經包括了我的GetFileContents功能太多,以防萬一)

Public Function UpdateCreateTables(ByVal SQLFilePath As String) As Boolean 
    'Open CREATE TABLE Script file 
    Dim strFilePath As String = SQLFilePath 
    Dim strErr As String = "" 
    Dim encEncoding As System.Text.Encoding = Nothing 
    Dim strContents As String = GetFileContents(strFilePath, encEncoding, strErr) 
    If strErr = "" Then 
     'Successfully Read 

     'Prepare 
     Dim SQLSCRIPT As String = "" & _ 
      "BEGIN TRANSACTION" & _ 
       "SET QUOTED_IDENTIFIER ON" & _ 
       "SET ARITHABORT ON" & _ 
       "SET NUMERIC_ROUNDABORT OFF" & _ 
       "SET CONCAT_NULL_YIELDS_NULL ON" & _ 
       "SET ANSI_NULLS ON" & _ 
       "SET ANSI_PADDING ON" & _ 
       "SET ANSI_WARNINGS ON" & _ 
      "COMMIT" 

     'Run Transaction Script 
     dbLocal.ExecuteNonQuery(SQLSCRIPT, Microsoft.SqlServer.Management.Common.ExecutionTypes.ContinueOnError) 

     'Inject All Table Names with a "TMP_" prefix 
     strContents = strContents.Replace("CREATE TABLE [dbo].[", "CREATE TABLE [dbo].[TMP_") 
     'Inject All Constraints with a TMP_ Prefix 
     strContents = strContents.Replace("CONSTRAINT [PK_", "CONSTRAINT [PK_TMP_") 

     SQLSCRIPT = strContents 

     'Run Script (Create TMP tables) 
     dbLocal.ExecuteNonQuery(SQLSCRIPT, Microsoft.SqlServer.Management.Common.ExecutionTypes.ContinueOnError) 

     'Loop through Each TMP table and copy original table data across 
     For Each dbTable As Table In dbLocal.Tables() 
      If dbTable.Name.Contains("TMP_") Then 
       Dim strTable_TempName As String = dbTable.Name 
       Dim strTable_OrigName As String = Strings.Replace(dbTable.Name, "TMP_", "") 

       Dim dbTempTable As Table = dbLocal.Tables(strTable_TempName) 
       Dim dbOrigTable As Table = dbLocal.Tables(strTable_OrigName) 

       'Get TmpTable Column Names 
       Dim strTempTable_Columns As String = "" 
       Dim strOrigTable_Columns As String = "" 
       For Each col As Column In dbTempTable.Columns 
        strTempTable_Columns = strTempTable_Columns & col.Name & ", " 
        'Find Matching Column in Orig Table 
        If dbOrigTable.Columns.Contains(col.Name) Then 
         strOrigTable_Columns = strOrigTable_Columns & col.Name & ", " 
        Else 
         strOrigTable_Columns = strOrigTable_Columns & "NULL" & ", " 
        End If 
       Next 
       strTempTable_Columns = Strings.Left(strTempTable_Columns, strTempTable_Columns.Length - 2) 'Remove trailing comma+space 
       strOrigTable_Columns = Strings.Left(strOrigTable_Columns, strOrigTable_Columns.Length - 2) 'Remove trailing comma+space 

       'alter LOCK_ESCALATION 
       dbTempTable.LockEscalation = LockEscalationType.Table 

       'Get Primary Key 
       Dim PK_Name As String = "" 
       For Each oIndex As Index In dbTempTable.Indexes 
        If oIndex.IndexKeyType = IndexKeyType.DriPrimaryKey Then 
         ' Primary key found 
         PK_Name = oIndex.Name 
        End If 
       Next 

       SQLSCRIPT = "" & _ 
        "BEGIN TRANSACTION" & vbCrLf & _ 
         "GO" & vbCrLf & _ 
         "SET IDENTITY_INSERT dbo." & strTable_TempName & " ON" & vbCrLf & _ 
         "GO" & vbCrLf & _ 
          "IF EXISTS(SELECT * FROM dbo." & strTable_OrigName & ")" & vbCrLf & _ 
          " EXEC('INSERT INTO dbo." & strTable_TempName & " (" & strTempTable_Columns & ")" & vbCrLf & _ 
          "  SELECT " & strOrigTable_Columns & " FROM dbo." & strTable_OrigName & " WITH (HOLDLOCK TABLOCKX)')" & vbCrLf & _ 
          " GO" & vbCrLf & _ 
         "SET IDENTITY_INSERT dbo." & strTable_TempName & " OFF" & vbCrLf & _ 
         "GO" & vbCrLf & _ 
         "DROP TABLE dbo." & strTable_OrigName & "" & vbCrLf & _ 
         "GO" & vbCrLf & _ 
         "EXECUTE sp_rename N'dbo." & PK_Name & "', '" & Replace(PK_Name, "TMP_", "") & "', 'OBJECT'" & vbCrLf & _ 
         "GO" & vbCrLf & _ 
         "EXECUTE sp_rename N'dbo." & strTable_TempName & "', N'" & strTable_OrigName & "', 'OBJECT'" & vbCrLf & _ 
         "GO" & vbCrLf & _ 
        "COMMIT" 

       'Run Transaction Script 
       dbLocal.ExecuteNonQuery(SQLSCRIPT, Microsoft.SqlServer.Management.Common.ExecutionTypes.ContinueOnError) 

      End If 
     Next 

     UpdateCreateTables = True 
    Else 
     UpdateCreateTables = False 
    End If 

End Function 
Public Function GetFileContents(ByVal FullPath As String, ByRef encEncoding As System.Text.Encoding, Optional ByRef ErrInfo As String = "") As String 
    Dim strContents As String 
    Dim objReader As StreamReader 

    Try 
     objReader = New StreamReader(FullPath, True) 
     encEncoding = objReader.CurrentEncoding 
     strContents = objReader.ReadToEnd() 
     objReader.Close() 
     Return strContents 
    Catch Ex As Exception 
     ErrInfo = Ex.Message 
     Return Nothing 
    End Try 
End Function