NVARCHAR和PATINDEX有什么问题?

时间:2016-02-24 08:54:52

标签: sql sql-server-2012

请找到我写的这个SQL函数

编辑:优化功能,就像在第一种情况下建议的那样

CREATE FUNCTION [dbo].[TL_ReplaceOldBrand]
(
    @string NVARCHAR(max),
    @BrandName NVARCHAR(50) = N'Brand',
    @BrandNameNew NVARCHAR(50) = N'NewBrand'
)
RETURNS NVARCHAR(max)
AS

BEGIN       
    DECLARE @ResultString NVARCHAR(max) = @string
    DECLARE @PossibleCharactersBegin NVARCHAR(100) = N'%[ ,.;:/?!-‘’''"(<>)' + Char(13) + Char(10) + ']'
    DECLARE @PossibleCharactersEnd NVARCHAR(100) = N'[ ,.;:/?!-‘’''"(<>)' + Char(13) + Char(10) + ']%'
    DECLARE @searchString NVARCHAR(100)

    --The brand name ONLY
    IF @ResultString = @BrandName
        SET @ResultString = REPLACE(@ResultString, @BrandName, @BrandNameNew)

    --The brand name at BEGINNING
    SET @searchString = N'' + @BrandName + @PossibleCharactersEnd
    WHILE PATINDEX(@searchString, @ResultString) > 0
    SET @ResultString = STUFF(@ResultString, PATINDEX(@searchString, @ResultString), LEN(@BrandName), @BrandNameNew)

    --The brand name BETWEEN words
    SET @searchString = N'' + @PossibleCharactersBegin + @BrandName + @PossibleCharactersEnd
    WHILE PATINDEX(@searchString, @ResultString) > 0
    SET @ResultString = STUFF(@ResultString, PATINDEX(@searchString, @ResultString) + 1, LEN(@BrandName), @BrandNameNew)

    --The brand name at the END
    SET @searchString = N'' + @PossibleCharactersBegin + @BrandName
    WHILE PATINDEX(@searchString, @ResultString) > 0
    SET @ResultString = STUFF(@ResultString, PATINDEX(@searchString, @ResultString) + 1, LEN(@BrandName), @BrandNameNew)

    RETURN @ResultString
END

当我像这样使用它时,就像这样:

select dbo.TL_ReplaceOldBrand(N'I want to replace, Brand by NewBrand, in a long long text which have multiple Brand occurences.', DEFAULT, DEFAULT)

没有发生替换。但是如果我在函数定义中用VARCHAR替换所有NVARCHAR,它就可以正常工作并按照我想要的那样用 NewBrand 替换 Brand

任何人都可以向我解释原因?

要回答这个问题,为什么我要使用NVARCHAR而不是VARCHAR,这是因为该函数用于包含多个语言文本的列,如中文,泰文或韩文等特殊字符

1 个答案:

答案 0 :(得分:0)

最后,我找到了另一个解决问题的方法

请找到我写的新功能

CREATE FUNCTION [dbo].[TL_ReplaceOldBrand]
(
    @string NVARCHAR(max),
    @BrandName VARCHAR(50) = N'Brand',
    @BrandNameNew VARCHAR(50) = N'NewBrand'
)
RETURNS NVARCHAR(max)
AS

BEGIN       
    DECLARE @ResultString VARCHAR(max) = @string
    DECLARE @NResultString NVARCHAR(max) = @string

    --REMARK: CHAR(13): Carriage Return
    --      : CHAR(10): Line Feed
    --      : CHAR(9) : Tabulation
    DECLARE @PossibleCharactersBegin VARCHAR(100) = N'%[ ,.;:/?!-‘’''"(<>)' + Char(13) + Char(10) + Char(9) + ']'
    DECLARE @PossibleCharactersEnd VARCHAR(100) = N'[ ,.;:/?!-‘’''"(<>)' + Char(13) + Char(10) + Char(9) + ']%'
    DECLARE @searchString VARCHAR(100)

    DECLARE @index int = 0

    --The brand name ONLY
    IF @NResultString = @BrandName
    BEGIN
        SET @NResultString = REPLACE(@NResultString, @BrandName, @BrandNameNew)
        SET @ResultString = CONVERT(VARCHAR(MAX), @NResultString)
    END

    --The brand name at BEGINNING
    SET @searchString = N'' + @BrandName + @PossibleCharactersEnd   
    SET @index = PATINDEX(@searchString, @ResultString)
    WHILE @index > 0
    BEGIN
        SET @NResultString = STUFF(@NResultString, @index, LEN(@BrandName), @BrandNameNew)
        SET @ResultString = @NResultString

        SET @index = PATINDEX(@searchString, @ResultString)
    END

    --The brand name BETWEEN words
    SET @searchString = N'' + @PossibleCharactersBegin + @BrandName + @PossibleCharactersEnd    
    SET @index = PATINDEX(@searchString, @ResultString)
    WHILE @index > 0
    BEGIN
        SET @NResultString = STUFF(@NResultString, @index + 1, LEN(@BrandName), @BrandNameNew)
        SET @ResultString = @NResultString

        SET @index = PATINDEX(@searchString, @ResultString)
    END

    --The brand name at the END
    SET @searchString = N'' + @PossibleCharactersBegin + @BrandName 
    SET @index = PATINDEX(@searchString, @ResultString)
    WHILE @index > 0
    BEGIN
        SET @NResultString = STUFF(@NResultString, @index + 1, LEN(@BrandName), @BrandNameNew)
        SET @ResultString = @NResultString

        SET @index = PATINDEX(@searchString, @ResultString)
    END

    RETURN @NResultString
END

我使用了替换变量来保持输入字符串的NVARCHAR格式,并在其VARCHAR等效项上使用patindex,它的工作正常。