如何使用SQL在MSI中更改列的数据类型?

时间:2015-08-13 22:49:55

标签: sql wix windows-installer

我在这里看到可以使用SQL更新MSI表模式 - https://msdn.microsoft.com/en-us/library/aa368562%28v=vs.85%29.aspx

(供参考:列定义格式 - https://msdn.microsoft.com/en-us/library/aa367870%28v=vs.85%29.aspx

我想将表格的列从SHORT(最大值32767)更改为INTEGER(最大值2147483647)。所有这些命令都给出了同样的错误:

CScript WiRunSQL.vbs Test.msi "ALTER TABLE `File` ALTER `Sequence` INTEGER"
Msi API Error 80004005: OpenView,Sql
1: 2237 2: C:\Test.msi 3: ALTER TABLE `File` ALTER `Sequence` INTEGER 4:

CScript WiRunSQL.vbs Test.msi "ALTER TABLE `File` ALTER COLUMN `Sequence` INTEGER"
Msi API Error 80004005: OpenView,Sql
1: 2237 2: C:\Test.msi 3: ALTER TABLE `File` ALTER COLUMN `Sequence` INTEGER 4:

CScript WiRunSQL.vbs Test.msi "ALTER TABLE `File` UPDATE `Sequence` INTEGER"
Msi API Error 80004005: OpenView,Sql
1: 2237 2: C:\Test.msi 3: ALTER TABLE `File` UPDATE `Sequence` INTEGER 4:

CScript WiRunSQL.vbs Test.msi "ALTER TABLE `File` MODIFY `Sequence` INTEGER"
Msi API Error 80004005: OpenView,Sql
1: 2237 2: C:\Test.msi 3: ALTER TABLE `File` MODIFY `Sequence` INTEGER 4:

我知道我可以通过Orca或InstEdit中的UI进行这些架构更改,并且我确信这些应用程序只是在底层运行SQL。我似乎无法弄清楚正确的陈述是什么......

更新:我最后编写了以下VB脚本以更新文件和媒体表(因为我需要更改其Sequence和LastSequence列的数据类型):

' MSI table schemas that need updating:
' Table    Column        Expected Data Type
' -----    ------        ------------------
' File     Sequence      SHORT
' Media    LastSequence  SHORT
'
'
' Structure of this script:
' 1. Create a FileTemp table, with the correct schema
' 2. Copy all the rows from File -> FileTemp
' 3. Delete the File table
' 4. Re-create the File table, with the correct schema
' 5. Copy all the rows from FileTemp -> File
' 6. Delete the FileTemp table
' 7. Repeat 1-6 for the Media table
'


Set Args = wscript.Arguments

If Args.Count() = 1 Then
   Dim fso
   Set fso = CreateObject("Scripting.FileSystemObject")
   strMsiPath = fso.GetAbsolutePathName(Args.item(0))
Else
    wscript.echo "Usage: UpdateSchema.vbs <full path to wix msi file>"
    Wscript.Quit 1
End If


'Open the MSI with read/write permissions
set installer = CreateObject("WindowsInstaller.Installer")
set db = installer.OpenDatabase(strMsiPath, 1)


'Step 0 (start clean)
'For testing purposees: if the "FileTemp" table exists -> delete it so
'that we start fresh with each run of this script
findFileTempTableSQL = "SELECT * FROM `_Tables` WHERE `Name`='FileTemp'"
Set fileTempView = db.OpenView(findFileTempTableSQL)
fileTempView.Execute()
Set fileTempRecord = fileTempView.Fetch
If fileTempRecord Is Nothing Then
   wscript.echo "***FileTemp Table does not exist (skipping...)"
Else
   wscript.echo "***FileTemp Table exists (deleting...)"
   dropTableSQL = "DROP TABLE `FileTemp`"
   Set dropTableView = db.OpenView(dropTableSQL)
   dropTableView.Execute()
   db.Commit
End If

'Global Strings
g_FileTableCreationDefinition = "(`File` CHAR(72) NOT NULL," &_
                                " `Component_` CHAR(72) NOT NULL," &_
                                " `FileName` CHAR(255) NOT NULL LOCALIZABLE," &_
                                " `FileSize` LONG NOT NULL," &_
                                " `Version` CHAR(72)," &_
                                " `Language` CHAR(20)," &_
                                " `Attributes` SHORT," &_
                                " `Sequence` SHORT NOT NULL" &_
                                " PRIMARY KEY `File`)"
g_FileTableInsertDefinition = "(`File`,`Component_`,`FileName`,`FileSize`,`Version`,`Language`,`Attributes`,`Sequence`)"
g_MediaTableCreationDefinition = "(`DiskId` SHORT NOT NULL," &_
                                 " `LastSequence` SHORT NOT NULL," &_
                                 " `DiskPrompt` CHAR(64) LOCALIZABLE," &_
                                 " `Cabinet` CHAR(255)," &_
                                 " `VolumeLabel` CHAR(32)," &_
                                 " `Source` CHAR(72)" &_
                                 " PRIMARY KEY `DiskId`)"
g_MediaTableInsertDefinition = "(`DiskId`,`LastSequence`,`DiskPrompt`,`Cabinet`,`VolumeLabel`,`Source`)"


'Update the File table to fix the `Sequence` column data type...'
'Step 1 - Create a FileTemp table, with the correct schema
CreateTable db, "FileTemp", g_FileTableCreationDefinition

'Step 2 - Copy all the rows from File -> FileTemp
CopyFileTableData db, "File", "FileTemp"

'Step 3 - Delete the File table
DropTable db, "File"

'Step 4 - Re-create the File table, with the correct schema
CreateTable db, "File", g_FileTableCreationDefinition

'Step 5 - Copy all the rows from FileTemp -> File
CopyFileTableData db, "FileTemp", "File"

'Step 6 - Delete the FileTemp table
DropTable db, "FileTemp"


'Update the Media table to fix the `LastSequence` column data type...'
'Step 1 - Create a MediaTemp table, with the correct schema
CreateTable db, "MediaTemp", g_MediaTableCreationDefinition

'Step 2 - Copy all the rows from Media -> MediaTemp
CopyMediaTableData db, "Media", "MediaTemp"

'Step 3 - Delete the Media table
DropTable db, "Media"

'Step 4 - Re-create the Media table, with the correct schema
CreateTable db, "Media", g_MediaTableCreationDefinition

'Step 5 - Copy all the rows from MediaTemp -> Media
CopyMediaTableData db, "MediaTemp", "Media"

'Step 6 - Delete the MediaTemp table
DropTable db, "MediaTemp"



'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Helper Sub-functions
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'This is a function that will copy 'File' table data
' arguments:
' db - the MSI database object
' sourceTableName - a string representing the table name were data will be copied 'from', e.g. "File"
' destTableName - a string representing the table name were data will be copied 'to', e.g. "FileTemp"
Sub CopyFileTableData(db, sourceTableName, destTableName)
   wscript.echo "***Copying rows from "+sourceTableName+" Table to "+destTableName+" Table..."
   Set view = db.OpenView("SELECT * FROM "+sourceTableName)
   view.Execute

   Do
      Set record = view.Fetch
      If record Is Nothing Then Exit Do

      File = record.StringData(1)
      Component_ = record.StringData(2)
      FileName = record.StringData(3)
      FileSize = record.StringData(4)
      Version = record.StringData(5)
      Language = record.StringData(6)
      Attributes = record.StringData(7)
      Sequence = record.StringData(8)
      recordValues = "('"+File+"','"+Component_+"','"+FileName+"',"+FileSize+",'"+Version+"','"+Language+"',"+Attributes+","+Sequence+")"

      insertSQL = "INSERT INTO "+destTableName+" "+g_FileTableInsertDefinition+" VALUES "+recordValues
      Set insertView = db.OpenView(insertSQL)
      insertView.Execute
      db.Commit
   Loop
End Sub


'This is a function that will copy 'Media' table data
' arguments:
' db - the MSI database object
' sourceTableName - a string representing the table name were data will be copied 'from', e.g. "Media"
' destTableName - a string representing the table name were data will be copied 'to', e.g. "MediaTemp"
Sub CopyMediaTableData(db, sourceTableName, destTableName)
   wscript.echo "***Copying rows from "+sourceTableName+" Table to "+destTableName+" Table..."
   Set view = db.OpenView("SELECT * FROM "+sourceTableName)
   view.Execute

   Do
      Set record = view.Fetch
      If record Is Nothing Then Exit Do

      DiskId = record.StringData(1)
      LastSequence = record.StringData(2)
      DiskPrompt = record.StringData(3)
      Cabinet = record.StringData(4)
      VolumeLabel = record.StringData(5)
      Source = record.StringData(6)
      recordValues = "("+DiskId+","+LastSequence+",'"+DiskPrompt+"','"+Cabinet+"','"+VolumeLabel+"','"+Source+"')"

      insertSQL = "INSERT INTO "+destTableName+" "+g_MediaTableInsertDefinition+" VALUES "+recordValues
      Set insertView = db.OpenView(insertSQL)
      insertView.Execute
      db.Commit
   Loop
End Sub


'This is a function that will create a MSI table
' arguments:
' db - the MSI database object
' tableName - a string representing the table name, e.g. "File"
' tableDefinitino - a string representing the table column definition, e.g. "(`File` CHAR(72) NOT NULL,...)"
Sub CreateTable(db, tableName, tableDefinition)
   Set view = db.OpenView("CREATE TABLE "+tableName+" "+tableDefinition)
   wscript.echo "***Creating '"+tableName+"' Table..."
   view.Execute
   db.Commit
End Sub


'This is a function that will drop any table from the MSI
' arguments:
' db - the MSI database object
' tableName - a string representing the table name, e.g. "File"
Sub DropTable(db, tableName)
   Set view = db.OpenView("DROP TABLE "+tableName)
   wscript.echo "***Dropping '"+tableName+"' Table..."
   view.Execute
   db.Commit
End Sub

0 个答案:

没有答案