TRANSLATE function in SQL SERVER

后端 未结 5 1765
醉酒成梦
醉酒成梦 2021-01-26 20:48

I read that there is a function equivalent to the standard function TRANSLATE under DB2 under SQL Server 2017. But how to do under earlier versions?

For definition of fu

5条回答
  •  北荒
    北荒 (楼主)
    2021-01-26 21:19

    Thought I'd put my idea in as well. This avoids the dreaded WHILE loop, and, also, doesn't use a self referencing variable (which can get ugly).

    Note the use of a Tally table, first, and then I use a Table Valued Function (rather than Scalar, which are slow) to do the work.

    Note, that I have set it so that if you provide fewer arguments on the right hand side, that the character will be removed. So, if the parameter @FindChars had the value 'AB' and @ReplaceChars the value 'C', then 'A' would be replaced with 'C' and 'B' would be replaced with ''. I note that with TRANSLATE this would produce the error The second and third arguments of the TRANSLATE built-in function must contain an equal number of characters.

    The problem, however, with a function is that you can't use things like THROW or RAISERROR. This means that actually producing an error inside a function isn't possible. You could, however, set something up so that NULL is returned if the two lengths don't match, but (unfortunately) the error production cannot be performed inside the function itself.

    CREATE VIEW dbo.Tally WITH SCHEMABINDING
    AS 
    
        WITH C1 AS (SELECT 1 AS I UNION ALL SELECT 1),
             C2 AS (SELECT 1 AS I FROM C1 AS L CROSS JOIN C1 AS R),
             C3 AS (SELECT 1 AS I FROM C2 AS L CROSS JOIN C2 AS R),
             C4 AS (SELECT 1 AS I FROM C3 AS L CROSS JOIN C3 AS R),
             C5 AS (SELECT 1 AS I FROM C4 AS L CROSS JOIN C4 AS R),
             C6 AS (SELECT 1 AS I FROM C5 AS L CROSS JOIN C5 AS R),
             RN AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS N FROM C6)
        SELECT TOP (1000000) N
        FROM RN
        ORDER BY N;
    GO
    
    CREATE FUNCTION dbo.OwnTranslate (@String varchar(8000),@FindChars varchar(8000), @ReplaceChars varchar(8000))
    RETURNS TABLE
    AS RETURN (
    
        WITH ToBeReplaced AS (
        SELECT @String AS String,
            FC.N,
            SUBSTRING(@FindChars, FC.N,1) AS FC,
            ISNULL(SUBSTRING(@ReplaceChars, RC.N,1),'') AS RC
        FROM (SELECT TOP (LEN(@FindChars)) N FROM Tally) FC
            OUTER APPLY (SELECT TOP (LEN(@ReplaceChars)) T.N FROM Tally T WHERE T.N = FC.N AND T.N <= LEN(@ReplaceChars)) RC),
        Replacing AS (
            SELECT N, REPLACE(String, FC, RC) AS ReplacedString
            FROM ToBeReplaced
            WHERE N = 1
            UNION ALL
            SELECT R.N + 1, REPLACE(ReplacedString, TBR.FC, TBR.RC) AS ReplacedString
            FROM ToBeReplaced TBR
                JOIN Replacing R ON TBR.N = R.N + 1)
        SELECT TOP 1 ReplacedString
        FROM Replacing
        ORDER BY N DESC);
    GO
    
    WITH VTE AS (
        SELECT *
        FROM (VALUES ('This is a string to be Translated.')) V(S))
    SELECT VTE.S, OT.ReplacedString
    FROM VTE
         CROSS APPLY dbo.OwnTranslate (VTE.S, 'Ts ', 'qz_') OT;
    
    GO
    --Clean up
    DROP FUNCTION dbo.OwnTranslate;
    DROP VIEW Tally;
    

    Any questions, please do ask.

提交回复
热议问题