确定性字符串替换和整理

时间:2017-06-21 11:22:53

标签: sql sql-server tsql

我有一个持久的计算列,调用Scalar Valued Function。如您所知,此函数需要具有确定性才能保持该值。即使REPLACE函数以确定的方式运行(我不能认为它不是这样的情况),SQL Server似乎将其​​解释为不确定的。因此,我不能在函数中使用它。

我尝试将一些非英语字符转换为英语。区分大小写在这里很重要。我想分别将ğĞüÜşŞıİöÖçÇ的字母转换为gGuUsSiIoOcC。我可以通过使用类似的东西来实现它(以#34;非确定性方式)#。

SET @ColumnValue = REPLACE(@ColumnValue COLLATE SQL_Latin1_General_CP1253_CS_AS, 'ı', 'i') --This character("ı") is converted to "?" after collation so that I manually replace it
SET @ColumnValue = @ColumnValue COLLATE SQL_Latin1_General_CP1253_CS_AS --This line takes care of the other characters

由于REPLACECOLLATE,SQL Server将上面的代码解释为非确定性(demo)(我认为它虽然是确定性的......)。

我尝试的另一件事是在WHILE循环中使用CHARINDEXSTUFF,但由于需要区分大小写,因此需要使用归类。如果没有排序规则,SQL Server会将其视为确定性的。

我有什么选择?

1 个答案:

答案 0 :(得分:5)

您的列真的是varchar类型,而不是nvarchar吗?

看起来COLLATE SQL_Latin1_General_CP1253_CS_ASnvarchar具有确定性,但对varchar具有不确定性。

以下功能是确定性的。 请注意,您需要在字符串文字前加N作为前缀才能正常工作。

CREATE FUNCTION dbo.TestFunc1 (@ColumnValue NVARCHAR(4000))
RETURNS NVARCHAR(4000)
WITH SCHEMABINDING
AS
BEGIN
    SET @ColumnValue = REPLACE(@ColumnValue COLLATE SQL_Latin1_General_CP1253_CS_AS, N'ı', N'i') --This character("ı") is converted to "?" after collation so that I manually replace it
    SET @ColumnValue = @ColumnValue COLLATE SQL_Latin1_General_CP1253_CS_AS --This line takes care of the other characters
    RETURN @ColumnValue
END

如果您需要使用varchar,那么我将使用二进制排序规则来替换特定字符。以下功能也是确定性的。

CREATE FUNCTION dbo.TestFunc2 (@ColumnValue VARCHAR(8000))
RETURNS VARCHAR(8000)
WITH SCHEMABINDING
AS
BEGIN
    SET @ColumnValue = REPLACE(@ColumnValue COLLATE Latin1_General_BIN2, N'ı', N'i')
    SET @ColumnValue = REPLACE(@ColumnValue COLLATE Latin1_General_BIN2, N'ö', N'o')

    ...

    RETURN @ColumnValue
END