WiX Toolset v3.11如何向已有数据库执行SqlString或SqlScript
WiX v3.11 向已存在数据库执行SQL的正确配置方法
报错根因
- CNDL5101触发原因:对官方文档的理解存在偏差。嵌套在Product/Fragment/Module下作为定位器的
SqlDatabase元素,不能直接嵌套SqlString/SqlScript子元素,所有SQL执行逻辑必须归属到某个Component下,仅数据库连接引用可以指向外层定义的定位器。 - CNDL5102触发原因:嵌套在Component下的
SqlDatabase元素,CreateOnInstall/CreateOnUninstall/DropOnInstall/DropOnUninstall四个属性不能全部设为no,必须至少显式指定一个属性值为yes,否则编译器无法判定该数据库记录关联的组件生命周期行为。
正确配置流程
- 先在Fragment层级定义独立的
SqlDatabase作为已有数据库的定位器,该标签下不嵌套任何SQL执行类子元素,仅配置数据库连接信息:
<Fragment> <!-- 外层仅作为已有数据库连接定位,不关联任何安装/卸载时的库操作 --> <sql:SqlDatabase Id="Database_MyDB" Server="[ComputerName]" Database="MyDB" Instance="MySQLInstance" /> </Fragment>
- 新建独立Component承载SQL执行逻辑,在Component内部编写
SqlString或SqlScript元素,通过SqlDatabase属性关联第一步定义的外层定位器ID,无需在Component内重复定义数据库连接:
<Fragment Id="FRG_Database"> <DirectoryRef Id="SQLFolder"> <Component Id="CMP_CreateMyTable" Guid="75FAEA47-E1E3-4A58-9528-4577968EA058" KeyPath="yes" Win64="yes"> <sql:SqlString Id="SQL_CreateMyTable" SqlDatabase="Database_MyDB" SQL="USE MyDB IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'MyTable') BEGIN CREATE TABLE MyTable ( Id INT PRIMARY KEY IDENTITY, Name NVARCHAR(50) NOT NULL, Timestamp DATETIME DEFAULT CURRENT_TIMESTAMP ) END" ContinueOnError="yes" ExecuteOnInstall="yes" /> </Component> </DirectoryRef> </Fragment>
- 在对应Feature节点下添加对上述
CMP_CreateMyTable组件的引用,否则组件不会随安装流程执行。
注意事项
- 外层作为定位器的
SqlDatabase不需要关联任何Component,不会触发数据库的创建或删除操作,完全适配连接目标机器已有数据库的场景。 - 若使用
SqlScript执行外部SQL文件,配置逻辑与SqlString一致:将SqlScript放在Component下,通过SqlDatabase属性指向外层定位器ID,同时关联对应脚本文件的Binary资源即可。 - 不要给外层定位器的
SqlDatabase添加任何Create/Drop类属性,也不要在Component内重复定义同名SqlDatabase,避免触发非预期的数据库操作。 - 安装包执行时需要确保运行安装程序的账号持有目标数据库的对应操作权限(如建表权限),否则SQL语句会执行失败。
内容的提问来源于stack exchange,提问作者APaglia
相关产品推荐
相关产品推荐

