db2*_*222 8 sql-server sql-server-2017
我们的客户安装 CU25 后,存储过程 sp_pkeys 出现问题。如果主键有多个列,它现在可能会返回错误的顺序。
可以在代码本身中找到它。这是 2017 款 CU25 变体:
create procedure sys.sp_pkeys
(
@table_name sysname,
@table_owner sysname = null,
@table_qualifier sysname = null
)
as
declare @table_id int
-- quotename() returns up to 258 chars
declare @full_table_name nvarchar(517) -- 258 + 1 + 258
if @table_qualifier is not null
begin
if db_name() <> @table_qualifier
begin -- If qualifier doesn't match current database
raiserror (15250, -1,-1)
return
end
end
if @table_owner is null
begin -- If unqualified table name
select @full_table_name = quotename(@table_name)
end
else
begin -- Qualified table name
if @table_owner = ''
begin -- If empty owner name
select @full_table_name = quotename(@table_owner)
end
else
begin
select @full_table_name = quotename(@table_owner) + '.' + quotename(@table_name)
end
end
select @table_id = object_id(@full_table_name)
select
TABLE_QUALIFIER = convert(sysname,db_name()),
TABLE_OWNER = convert(sysname,schema_name(o.schema_id)),
TABLE_NAME = convert(sysname,o.name),
COLUMN_NAME = convert(sysname,c.name),
KEY_SEQ = (SELECT convert(smallint, index_column_id)
FROM sys.index_columns
WHERE object_id = @table_id AND index_id = i.index_id and column_id = c.column_id),
PK_NAME = convert(sysname,k.name)
from
sys.indexes i,
sys.all_columns c,
sys.all_objects o,
sys.key_constraints k
where
o.object_id = @table_id and
o.object_id = c.object_id and
o.object_id = i.object_id and
k.parent_object_id = o.object_id and
k.unique_index_id = i.index_id and
i.is_primary_key = 1 and
c.column_id IN
(SELECT column_id
FROM sys.index_columns
WHERE object_id = @table_id AND index_id = i.index_id)
order by 1, 2, 3, 5
Run Code Online (Sandbox Code Playgroud)
这是 SQL Server 2017 CU24 和 SQL Server 2019 变体:
create procedure sys.sp_pkeys
(
@table_name sysname,
@table_owner sysname = null,
@table_qualifier sysname = null
)
as
declare @table_id int
-- quotename() returns up to 258 chars
declare @full_table_name nvarchar(517) -- 258 + 1 + 258
if @table_qualifier is not null
begin
if db_name() <> @table_qualifier
begin -- If qualifier doesn't match current database
raiserror (15250, -1,-1)
return
end
end
if @table_owner is null
begin -- If unqualified table name
select @full_table_name = quotename(@table_name)
end
else
begin -- Qualified table name
if @table_owner = ''
begin -- If empty owner name
select @full_table_name = quotename(@table_owner)
end
else
begin
select @full_table_name = quotename(@table_owner) + '.' + quotename(@table_name)
end
end
select @table_id = object_id(@full_table_name)
select
TABLE_QUALIFIER = convert(sysname,db_name()),
TABLE_OWNER = convert(sysname,schema_name(o.schema_id)),
TABLE_NAME = convert(sysname,o.name),
COLUMN_NAME = convert(sysname,c.name),
KEY_SEQ = convert (smallint,
case
when c.name = index_col(@full_table_name, i.index_id, 1) then 1
when c.name = index_col(@full_table_name, i.index_id, 2) then 2
when c.name = index_col(@full_table_name, i.index_id, 3) then 3
when c.name = index_col(@full_table_name, i.index_id, 4) then 4
when c.name = index_col(@full_table_name, i.index_id, 5) then 5
when c.name = index_col(@full_table_name, i.index_id, 6) then 6
when c.name = index_col(@full_table_name, i.index_id, 7) then 7
when c.name = index_col(@full_table_name, i.index_id, 8) then 8
when c.name = index_col(@full_table_name, i.index_id, 9) then 9
when c.name = index_col(@full_table_name, i.index_id, 10) then 10
when c.name = index_col(@full_table_name, i.index_id, 11) then 11
when c.name = index_col(@full_table_name, i.index_id, 12) then 12
when c.name = index_col(@full_table_name, i.index_id, 13) then 13
when c.name = index_col(@full_table_name, i.index_id, 14) then 14
when c.name = index_col(@full_table_name, i.index_id, 15) then 15
when c.name = index_col(@full_table_name, i.index_id, 16) then 16
end),
PK_NAME = convert(sysname,k.name)
from
sys.indexes i,
sys.all_columns c,
sys.all_objects o,
sys.key_constraints k
where
o.object_id = @table_id and
o.object_id = c.object_id and
o.object_id = i.object_id and
k.parent_object_id = o.object_id and
k.unique_index_id = i.index_id and
i.is_primary_key = 1 and
(c.name = index_col (@full_table_name, i.index_id, 1) or
c.name = index_col (@full_table_name, i.index_id, 2) or
c.name = index_col (@full_table_name, i.index_id, 3) or
c.name = index_col (@full_table_name, i.index_id, 4) or
c.name = index_col (@full_table_name, i.index_id, 5) or
c.name = index_col (@full_table_name, i.index_id, 6) or
c.name = index_col (@full_table_name, i.index_id, 7) or
c.name = index_col (@full_table_name, i.index_id, 8) or
c.name = index_col (@full_table_name, i.index_id, 9) or
c.name = index_col (@full_table_name, i.index_id, 10) or
c.name = index_col (@full_table_name, i.index_id, 11) or
c.name = index_col (@full_table_name, i.index_id, 12) or
c.name = index_col (@full_table_name, i.index_id, 13) or
c.name = index_col (@full_table_name, i.index_id, 14) or
c.name = index_col (@full_table_name, i.index_id, 15) or
c.name = index_col (@full_table_name, i.index_id, 16))
order by 1, 2, 3, 5
Run Code Online (Sandbox Code Playgroud)
关键是如何KEY_SEQ
确定。如果使用第二种变体,它将正常工作。
或者,如果子选择像这样完成,那么第一个变体也可以工作:
SELECT convert(smallint, key_ordinal)
FROM sys.index_columns
WHERE object_id = @table_id AND index_id = i.index_id and column_id = c.column_id
Run Code Online (Sandbox Code Playgroud)
因此需要使用 key_ordinal 而不是 index_column_id 。
然而,由于它是一个系统存储过程,因此似乎不可能更改它,至少在没有非常关键和不建议的步骤的情况下是不可能的。
除了降级或等待 Microsoft 修复(解决方法)之外,还有其他选择吗?
联系 Microsoft 以尽快获得修复的最佳方式是什么?
Microsoft 在CU25 的发行说明中写了有关 sp_pkeys 的更改。
向系统 sp_pkeys 添加了对 32 个键列的支持,并修复了安装 SQL Server 2017 累积更新 21 (CU21) 后出现的性能下降问题
仅供参考:与刚刚发布的CU26没有区别。
除了降级或等待 Microsoft 修复(解决方法)之外,还有其他选择吗?
对于系统过程的问题没有任何支持,不。
联系 Microsoft 以尽快获得修复的最佳方式是什么?
向Microsoft 支持开立案例。
我相信如果确认原因是产品缺陷,他们会退还费用。
此问题已在SQL Server 2017 CU27和SQL Server 2019 CU15中得到解决。
归档时间: |
|
查看次数: |
655 次 |
最近记录: |