2014-03-27 58 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