与 Visual Studio 2017 中的架构比较的意外差异
Posted
技术标签:
【中文标题】与 Visual Studio 2017 中的架构比较的意外差异【英文标题】:unexpected differences from Schema Compare in Visual Studio 2017 【发布时间】:2018-04-09 14:29:23 【问题描述】:我在Visual Studio 2017
中有Schema Compare
的这种奇怪行为。
在比较 2 个数据库时,我发现两个相同的表不同,其中一个没有 PK
名称。如果我使用SSMS
编写表脚本,我会看到确实在其中一台服务器上的表脚本似乎没有PK
名称,但如果我查询sys.indexes
表,我会发现该索引具有相同的名称在两台服务器上。
我找到的一个可能的解决方案是更新表,假设添加一些随机索引并删除它,所以我猜测它与 SQL Server 如何存储对象定义有关。但是很高兴知道是什么导致了这个问题以及如何以正确的方式解决它,而不是通过某种解决方法。
附言我知道PK
的名字不是“正确的”。
比较两个相同的SPs
时的类似情况。我尝试运行 sp_refreshsqlmodule
和 sp_recompile
但它没有帮助。更新 SP
会有所帮助,但这又不是很好的解决方法。
编辑 1:在第一个示例中,两个数据库上都存在同名的 PK(即使名称不符合标准)。在两个数据库上运行的以下查询返回相同的结果:
SELECT I.name
FROM sys.indexes AS I
INNER JOIN sys.objects AS O
ON O.object_id = I.object_id
INNER JOIN sys.schemas AS S
ON S.schema_id = O.schema_id
WHERE S.name = 'MySchema'
AND O.name = 'MyName'
结果:PK__TraceDat__AAAC09D801ED28A5
【问题讨论】:
【参考方案1】:您注意到的两件事都是由于脚本的不良做法造成的,并且是可能导致问题的具体问题。虽然现在可能没有眼前的问题,但未来可能会有。
在第一种情况下,您已经指出了根本问题,左侧没有 PK 的名称,而右侧有一些名称。实际上,所有的约束总是都有一个名字,你可以明确指出它,它就是名字。但是,如果创建脚本没有指示名称(如您的左侧),服务器将为约束创建一个随机名称(这就是您在右侧看到的)。这是一个问题,因为不同的服务器将有不同的约束名称(如果有多个数据库实例),并且如果您以后想要删除或更改约束,您将没有具体的名称来引用约束。真正的解决办法很简单,自己给约束起个名字,这样就有固定的引用了。
第二种情况更糟。唯一的区别是左侧有一个没有模式的过程,而右侧它被明确定义为dbo
。数据库中的每个对象都存在于模式中,如果没有明确指出,则使用用户的默认模式来确定它。为什么这是一种不好的做法有多种原因(例如,在多模式数据库中,可能会出现歧义或选择错误的表,性能也会受到负面影响),因此解决方案是在以下情况下简单地命名正确的模式创建或修改表(查询也很重要,尽管此处无关)。
【讨论】:
我完全同意这些都是不好的做法,没有争论,但是: 1. 两个数据库中都有一个 PK 并且它是相同的(参见编辑 1),只是模式比较出于某种原因认识到这不一样。 2. 正如你提到的,对象不能没有模式,如果我查询系统对象,我会看到它属于dbo
模式。我对为什么 Schema Compare
引擎将这些标记为差异感兴趣。
在这两种情况下,答案都是“因为它们不同”。在 1 中,约束仅在名称上有所不同意味着它们现在的工作方式相同,但更改脚本必须不同(以应对更改的名称),所以这是不同的。在 2 中,缺少架构意味着创建时分配的真实架构可能会根据数据库设置而有所不同,之后再次创建非确定性更改脚本。通过在这两种情况下都明确说明,您可以确保无论上下文如何,您始终获得相同的数据库。
1.名字是一样的。请阅读编辑 1。名称不遵循约定,是的,但在两个数据库上都是相同的。两者的更改脚本都是相同的。 (测试过) 2.可以,但不是。在这种情况下,默认架构是 dbo
。【参考方案2】:
我有时在重命名对象后使用 Apex sql diff 会遇到类似的问题。尝试删除/创建。这是问题的潜在原因。
【讨论】:
以上是关于与 Visual Studio 2017 中的架构比较的意外差异的主要内容,如果未能解决你的问题,请参考以下文章
传入 Lambda 时,Visual Studio 2017 中的哪些扩展可以消除“bool”与“std::function”的歧义?