PAYATHON 2026

VS Code/Rider 的 Schema Compare 如何处理 SQLCMD 变量差异?

数据阿明

结论

这段 XML 符合 SQL 项目中声明 SQLCMD 变量的一般格式。不过,添加 DefaultValue 无法保证 Schema Compare 将 [$(DatabaseName)] 与实际数据库名称视为相同。

先确认 DatabaseName 指向当前项目自身的数据库还是另一个数据库。如果是当前数据库,且 SQL 语义允许,优先使用 [schema].[object] 两段式名称,可以避开这类变量解析差异。如果是另一个数据库,则需要检查数据库引用配置、比较时使用的变量值,以及比较工具是否包含相关修复。

为什么切换复选框仍有差异?

DoNotEvaluateSqlCmdVariables 控制比较时使用 SQLCMD 变量名称还是变量值。取消勾选允许按值比较,并不意味着所有涉及变量的差异都会被忽略。比较工具仍需正确取得变量值并处理相应的模型引用。DacFx 属性说明

.sqlproj 中的 DefaultValue 不会编译进 .dacpac,它用于为图形发布界面提供默认值。因此,即使修改默认值后重新构建,也不能据此认定 .dacpac 的比较过程已经获得该值。SQLCMD 变量文档

VS Code 的问题记录区分了普通跨数据库变量和项目自身的 $(DatabaseName)。2026 年 10 月 28 日,维护者指出,当时针对跨数据库变量的修复未覆盖 DatabaseName 自引用,显式声明该变量也无法解决,相关问题由 #23173 跟踪。该记录可以解释 VS Code 中的现象,但 Rider 是否有相同原因,还需要结合其版本和最小复现确认。相关问题及维护说明

当前数据库的对象:优先使用两段式名称

SQL 项目自动提供 $(DatabaseName),用于需要三段式名称的当前数据库引用。普通的同库对象引用通常不需要数据库名前缀。数据库引用文档

例如,以下代码中的表名仅作演示:

SELECT Id
FROM [$(DatabaseName)].[dbo].[SomeTable];

如果它确实访问当前数据库中的对象,可以改为:

SELECT Id
FROM [dbo].[SomeTable];

修改后重新构建项目,再对同一个对象运行 Schema Compare,检查是否还存在其他差异。

还需核对执行上下文。如果对象必须通过数据库名前缀访问,或者代码实际访问其他数据库,就应保留相应限定,继续排查变量解析。

其他数据库的对象:检查引用和变量取值

跨数据库引用的变量声明需要与数据库引用配置对应。例如,下面使用 OtherDatabase 作为演示变量名:

<ItemGroup>
  <ProjectReference Include="../OtherDatabase/OtherDatabase.sqlproj">
    <DatabaseSqlCmdVariable>OtherDatabase</DatabaseSqlCmdVariable>
  </ProjectReference>
  <SqlCmdVariable Include="OtherDatabase">
    <DefaultValue>ActualOtherDatabase</DefaultValue>
    <Value>$(SqlCmdVar__1)</Value>
  </SqlCmdVariable>
</ItemGroup>

SQL 中使用同一个变量名:

SELECT Id
FROM [$(OtherDatabase)].[dbo].[SomeTable];

项目路径、数据库名称和对象名称都需要替换为实际值。DatabaseSqlCmdVariable 将数据库引用与 SQL 中的变量关联起来,单独增加一个 SqlCmdVariable 不能代替数据库引用。数据库引用配置

建议按以下顺序验证:

  1. 确认比较对象是项目还是已构建的 .dacpac,并确认使用的是预期输入。
  2. 确认普通变量的取值与数据库定义中的实际名称一致。如果工具提供比较专用的变量设置,也要检查该设置。
  3. 核对 VS Code 扩展或 Rider 的发布说明,确认所用版本是否包含对应修复。问题记录中的修复说明不能直接证明本机版本已包含修复,也不能证明 Rider 同步修复。
  4. 用一个变量和一个引用对象建立最小复现,区分自引用、跨数据库引用和其他结构差异。

需要保留变量时,如何继续检查差异?

可以使用 SqlPackage 显式传入普通 SQLCMD 变量,生成部署报告,辅助检查部署计划。下面的 PowerShell 示例假设环境支持 Windows 集成身份验证:

SqlPackage /Action:DeployReport /SourceFile:"./bin/Debug/App.dacpac" /TargetConnectionString:"Server=localhost;Database=AppDb;Integrated Security=True;Encrypt=True" /v:OtherDatabase=ActualOtherDatabase /OutputPath:"./compare.xml"

请替换 .dacpac 路径、连接字符串和变量值;项目有多个变量时,应提供所需的全部取值。DeployReport 生成描述计划发布变更的 XML 报告,不执行发布。SqlPackage DeployReport 文档

这份报告有助于区分图形比较界面的问题和部署计划中的差异,但不能保证绕过 DatabaseName 自引用问题,也不会修复 IDE 中的显示。

如果数据库名称长期固定,也可以考虑使用字面量名称,但这样会失去按环境替换名称的便利。对于需要适配多个环境的项目,优先保留变量,并验证比较工具对相应引用场景的支持情况。逐项排除差异只适合临时处理已经人工确认的噪声,以免连同真实结构变更一起跳过。

备注:内容仅供参考。