更改作为主键方的字段时出错,仅在一台服务器上
Posted
技术标签:
【中文标题】更改作为主键方的字段时出错,仅在一台服务器上【英文标题】:Error when altering field that is party of primary key, only on one server 【发布时间】:2019-07-29 14:25:56 【问题描述】:我有两台MSSQL Server,一台是SQL Server 2016,另一台是SQL Server 2017。
在 SQL Server 2016 上,当我运行此代码时:
ALTER TABLE [FSFIELDLABEL] ALTER COLUMN [VALIDATION_CODE] NVARCHAR(30) NOT NULL;
然后我得到预期的错误:
Msg 5074, Level 16, State 1, Line 3
The object 'FS_FIELDLABEL_PK' is dependent on column 'VALIDATION_CODE'.
Msg 4922, Level 16, State 9, Line 3
ALTER TABLE ALTER COLUMN VALIDATION_CODE failed because one or more objects access this column.
但是,当我在 SQL Server 2017 上运行相同的命令时,我没有收到错误消息。我检查了,两个数据库上都存在相同的主键,一个在2016服务器上,一个在2017服务器上。
我可以查看哪些用户权限或数据库设置来尝试确定这两个服务器的行为为何不同? 2017 服务器是我们的开发人员测试的对象,所以当他们测试在 2017 服务器上“工作”但在 2016 服务器上失败的代码时,它真的把我们搞砸了。
2017 年“无错误”表的 SQL 创建
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[FSFIELDLABEL](
[LANGUAGE_CODE] [nvarchar](20) NOT NULL,
[VALIDATION_CODE] [nvarchar](30) NOT NULL,
[DATA_NAME] [nvarchar](32) NOT NULL,
[RECFMT_CODE] [nvarchar](4) NOT NULL,
[LINE_ID] [smallint] NOT NULL,
[LABEL] [nvarchar](500) NULL,
[FORMAT_CODE] [nvarchar](20) NULL,
[VERSION] [nvarchar](10) NULL,
[FS_SYS_ROWID] [int] NULL,
[TOOLTIP] [nvarchar](512) NULL,
[DISPLAY_TOOLTIP] [smallint] NOT NULL,
CONSTRAINT [FS_FIELDLABEL_PK] PRIMARY KEY CLUSTERED
(
[LANGUAGE_CODE] ASC,
[VALIDATION_CODE] ASC,
[DATA_NAME] ASC,
[RECFMT_CODE] ASC,
[LINE_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[FSFIELDLABEL] ADD DEFAULT ('A') FOR [RECFMT_CODE]
GO
ALTER TABLE [dbo].[FSFIELDLABEL] ADD DEFAULT ((0)) FOR [LINE_ID]
GO
ALTER TABLE [dbo].[FSFIELDLABEL] ADD DEFAULT (' ') FOR [LABEL]
GO
ALTER TABLE [dbo].[FSFIELDLABEL] ADD DEFAULT ((1)) FOR [DISPLAY_TOOLTIP]
GO
2016 年“非工作”服务器的 SQL 创建
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[FSFIELDLABEL](
[LANGUAGE_CODE] [nvarchar](20) NOT NULL,
[VALIDATION_CODE] [nvarchar](20) NOT NULL,
[DATA_NAME] [nvarchar](32) NOT NULL,
[RECFMT_CODE] [nvarchar](4) NOT NULL CONSTRAINT [DF__FSFIELDLA__RECFM__63F8CA06] DEFAULT ('A'),
[LINE_ID] [smallint] NOT NULL CONSTRAINT [DF__FSFIELDLA__LINE___64ECEE3F] DEFAULT ((0)),
[LABEL] [nvarchar](500) NULL CONSTRAINT [DF__FSFIELDLA__LABEL__65E11278] DEFAULT (' '),
[FORMAT_CODE] [nvarchar](20) NULL,
[VERSION] [nvarchar](10) NULL,
[FS_SYS_ROWID] [int] NULL,
[TOOLTIP] [nvarchar](512) NULL,
[DISPLAY_TOOLTIP] [smallint] NOT NULL CONSTRAINT [DF__FSFIELDLA__DISPL__2DA7A64D] DEFAULT ((1)),
CONSTRAINT [FS_FIELDLABEL_PK] PRIMARY KEY CLUSTERED
(
[LANGUAGE_CODE] ASC,
[VALIDATION_CODE] ASC,
[DATA_NAME] ASC,
[RECFMT_CODE] ASC,
[LINE_ID] ASC
)WITH (PAD_INDEX = ON, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
【问题讨论】:
文档似乎暗示它也不应该在 SQL Server 2017 上运行:docs.microsoft.com/en-us/sql/t-sql/statements/…。能否请您为每台服务器上的表发布完整的 CREATE TABLE 脚本? 将请求的 Create Table 脚本添加到原始问题中。 感谢您发布此内容,我看不到那里的架构有任何问题。 2016 年和 2017 年服务器的表中存储的数据有什么不同吗? 两个表之间的数据不相同,但非常相似。工作表3599行,非工作表4050行。 【参考方案1】:也许,您的列在 SQL Server 2016 中具有值。另一方面,在 SQL 2017 中,您的列没有值。
您可以删除 FS_FIELDLABEL_PK
并更改您的数据类型,然后再次添加您的约束。
【讨论】:
【参考方案2】:我尝试比较以下页面:
https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql?view=sql-server-2016
https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql?view=sql-server-2017
我发现它们是相同的。
我建议您获取引用列 VALIDATION_CODE 的所有对象(尤其是视图)的列表,以及服务器中是否存在具有架构绑定的对象 2016 而不是 2017。
使用 SQL 搜索或类似工具应该很容易获得列表。
https://www.red-gate.com/products/sql-development/sql-search/
已编辑:
这是一个非常有趣的问题,我尝试在 SQL Server 2016 上重现该问题,我发现我可以重现此问题,但前提是更改列的新大小小于当前大小( nvarchar(30)以 nvarchar(29) 为例),保持相同大小或增加大小将不会产生此问题,无论表是否为空都没有影响。
我相信这是这个问题的对应解释,根据offcial documentation:
更改列
修改后的列不能是:
用于由 CREATE STATISTICS 语句生成的统计信息。 除非列是 varchar、nvarchar 或 varbinary 数据类型,否则 数据类型没有改变。并且,新尺寸等于或大于 旧尺寸。或者,如果列从非空更改为空。 首先,使用 DROP STATISTICS 语句删除统计信息。
所以问题是由于使用主键自动添加的 STATISTICS。
我建议在 ALTER 语句之前删除主键,然后将其添加回来。
【讨论】:
遗憾的是,我们正在将 Nvarchar(20) 更改为 Nvarchar(30)。如果我们减小大小,我们会在所有服务器上看到错误,但增加大小只会在 2016 服务器上出现错误。 您能否检查是否有除 [FS_FIELDLABEL_PK] 之外的任何 STATISTICS 在您的 2016 服务器上自动创建,并尝试在 ALTER 语句之前删除它们? 我认为没有任何统计信息或任何相关的统计信息,因为一旦我删除了主键以及碰巧存在的任何索引,我就可以很好地更改列。我只是不明白为什么 2017 Server 不关心是否存在索引或主键。 最后,我无法重现同样的问题,所以我无法提供更多信息。以上是关于更改作为主键方的字段时出错,仅在一台服务器上的主要内容,如果未能解决你的问题,请参考以下文章
VBS 在一台服务器上运行 .xlsm 工作簿中的 VBA 宏,但在另一台服务器上运行良好