Mik*_*nov 6 sql-server collation partitioning
我正在尝试更改列的排序规则:
ALTER TABLE [dbo].[yourdad] ALTER COLUMN [yourmam] varchar(36) COLLATE SQL_Latin1_General_CP1_CI_AI NOT NULL;
Run Code Online (Sandbox Code Playgroud)
它给出了这样的消息:
消息 5074,级别 16,状态 1,第 1 行 对象“yourdad”依赖于列“yourmam”。消息 4922,级别 16,状态 9,第 1 行 ALTER TABLE ALTER COLUMN yourmam 失败,因为一个或多个对象访问此列。
它具有依赖于该列的分区模式和功能。
目前我喜欢超过 40k 的表,其中包含应该更改排序规则的列。
是否可以在不重新创建表格的情况下更改排序规则?
删除分区索引 - 删除。
但是当我尝试删除架构时:
删除分区方案你爸爸
消息 7717,级别 16,状态 1,第 1 行 分区方案“yourdad”当前正用于对一个或多个表进行分区。
这是我不想安装的数据库上的一种新的不区分大小写的数据库整理,旧的是 - 区分大小写。
您不需要删除表。
一种选择(我已经测试过)是:
删除并重新创建分区函数以使用COLLATE输入参数的新排序规则指定子句(这里假设您没有更改数据库的默认排序规则,并且输入参数将使用数据库的字符串类型默认排序规则,除非指定使用该COLLATE条款,并CREATE INDEX使用该方案和功能,如果该参数的排序规则不匹配的分区列的排序规则将失败语句)。意思是,如果您将列的排序规则更改为SQL_Latin1_General_CP1_CI_AI但数据库仍在使用SQL_Latin1_General_CP1_CI_AS,那么您需要:
CREATE PARTITION FUNCTION PartitionFunc
(
VARCHAR(36) COLLATE SQL_Latin1_General_CP1_CI_AI
)
...
Run Code Online (Sandbox Code Playgroud)现在,40k+ 个表可能不止几个,但如果它们都使用相同的分区方案和功能,那么与您已经需要的相比,这只是 4 个额外的语句(为分区模式和分区功能创建和删除)即使没有使用分区(即,无论如何您都需要删除并重新创建索引)。因此,虽然这在删除和重新创建索引时确实需要大量 I/O,但在更改列的排序规则时无法解决这个问题。
我假设(并且手指交叉)这些列不是:
如果其中任何一种情况属实,那么您还有很多工作要做,但这与分区无关。
另一种选择(考虑到不想重新创建所有内容)可能是使用未记录的sqlservr.exe -q选项来更改实例上所有用户列和数据库的排序规则。这种方法会更改数据库、列、参数等的元数据,然后重建索引(同样,在更改排序规则时无法解决此问题,因此对于 40k+ 表,这可能需要几分钟(或更长时间)并且数据库或整个实例(如果您全局更新排序规则)在此期间将处于脱机状态)。
我只是测试上的SQL Server 2019 RC1这种情况下,它也不能对分区功能的工作,但是,这并不意味着,这种做法是不是整体解决方案的一部分。这只是意味着你真的别无选择,只能完成上一节中提到的过程。该SQLSERVR.EXE -q方法将处理一切(除用户定义的表类型,我相信)。能够更改列的排序规则有很多限制,更改数据库的默认排序规则(两种情况下都有很多依赖项)的限制更多,所以如果您现在想要一个区分大小写的数据库,那么您可能会除了分区列之外还有其他障碍。
不适用于分区函数的是输入参数的排序规则存储在sys.partition_parameters. 这个特殊的元数据不会被其他很棒的甚至如果未记录的-q选项改变。这样做的效果是:
假设数据要么VARCHAR没有更改代码页,要么NVARCHAR,那么数据仍将像以前一样进行分区。例如,假设您有一个RANGE LEFT使用FOR VALUES ( 'D', 'H', 'O', 'V' ). 在这种情况下,分区 #2 包含值> D和<= H。
SQL_Latin1_General_CP1_CI_AI,分区 #2 将包含E, e, F, f, G, g, H, h。够简单了吧?SQL_Latin1_General_CP1_CS_AI,分区 #2 将包含d, E, e, F, f, G, g, H。此分区现在包含小写d,不包含小写h。这是因为大多数 SQL Server 排序规则在小写之前排序大写(Windows 排序规则首先排序小写)。VARCHAR和代码页不同,那么事情可能会变得有趣。值在 128 和 255 之间的任何字符都可能具有不同的值和/或排序位置,被映射到类似的字符,因为它在用于分区函数整理的整理代码页上不可用(即“最佳拟合”映射),或者它可能在旧代码页中丢失,因此它变成了一个“ ? ”并按那个排序。根据正在使用的字符、它们如何映射(如果它们甚至这样做)到另一个代码页以及如何设置分区范围,您可能会遇到从“根本没有影响”到“非常奇怪和困难”的任何事情跟踪/调试行为”。我已经提交了将这个特定的元数据添加到sqlservr.exe -q操作的请求,但微软没有真正的动力来修复它,因为它是一个未记录的功能。所以,请支持它(即投票给它),这样他们至少可以看到人们确实想要它(谢谢!): 通过 SQLSERVR -Q 更新分区函数和用户定义表类型的排序规则
话虽如此,两个主要问题是:
首先更改排序规则有什么影响?什么是当前归类,什么是新归类?
如果代码页正在更改,是否会丢失数据(问题中的示例代码显示了一个VARCHAR列,这使得这种情况成为可能;对于 而言并非如此NVARCHAR)?这种方法并没有做一个代码页转换,所以用128和255之间的值的字符可能会成为一些其它字符,并且没有警告/当这种情况发生的错误(但如果你没有这样的数据,那么这是一个非-问题)。
如果敏感度发生变化(即从 Accent-Sensitive 变为 Accent-Insensitive),那么现在是否会违反现有唯一索引/约束中的唯一性?
有关此方法的完整详细信息,请参阅我的帖子:
更改所有用户数据库中的实例、数据库和所有列的排序规则:可能出现什么问题?(请务必查看“查找和修复被忽略的对象”部分,其中包含帮助修复分区功能的查询)
如果您有多个数据库并且只想更改这个数据库(同样,此数据库中的所有内容,包括数据库的默认排序规则),那么您可以:
sqlservr.exe -q方法更新临时实例的排序规则。