本文介绍了SQL SERVER 中的 TRANSLATE 函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读到SQL Server 2017下DB2下有一个相当于标准函数TRANSLATE的函数,但是在早期版本下怎么做?

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?

函数定义:这里

推荐答案

改编自 @Shnugo 的回答.这更接近你想要的.你只需要确保你有一个 dbo.numbers(它们真的很有用).

Adapted from @Shnugo's answer. This is closer to what you want. You just need to make certain you have a dbo.numbers table (they're REALLY useful to have).

http://dbfiddle.uk/?rdbms=sqlserver_20843616182016182016161820161820161616182016161820161616182016161820161520161616152016161615201616161615201616161531313ba384a8&fiddle一个>

http://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=627828307504174dcf3f61313ba384a8

CREATE FUNCTION dbo.MultiReplace(@ReplaceTarget NVARCHAR(MAX), @from_chars NVARCHAR(MAX), @to_chars NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
    --Quirky Update: One of the rare situations where this is a good idea
    SELECT @ReplaceTarget=REPLACE(@ReplaceTarget,SUBSTRING(@from_chars, id+1, 1), SUBSTRING(@to_chars, id+1, 1))
    FROM numbers
    WHERE id < LEN(@from_chars) AND id < LEN(@to_chars)
    ORDER BY id;

    RETURN @ReplaceTarget;
END


还有一种稍微过分的方式来满足您的要求 TRANSLATE('abc', 'abc', 'bcd') =>'bcd').

And a slightly over the top way to meet your requirement that TRANSLATE('abc', 'abc', 'bcd') => 'bcd').

CREATE FUNCTION dbo.Translate(@ReplaceTarget NVARCHAR(MAX), @from_chars NVARCHAR(MAX), @to_chars NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN

  DECLARE
    @steps INT = LEN('_' + @from_chars + '_') - 2
  ;

  WITH
    dictionary(id, string_from, string_interim, string_to) AS
  (
    SELECT
      id, string_from, N'<' + string_from + N'>', string_to
    FROM
    (
      SELECT
        id,
        ROW_NUMBER() OVER (PARTITION BY string_from ORDER BY id)  AS occurence,
        string_from,
        string_to
      FROM
        numbers
      CROSS APPLY
      (
        SELECT
          CAST(SUBSTRING(@from_chars, numbers.id, 1) AS NVARCHAR(5))  AS string_from,
          CAST(SUBSTRING(@to_chars,   numbers.id, 1) AS NVARCHAR(5))  AS string_to
      )
        chars
      WHERE
            numbers.id >  0
        AND numbers.id <= @steps
    )
      sorted_dictionary
    WHERE
      occurence = 1
  )
  ,
    mapping_sequence(id, string_from, string_to) AS
  (
              SELECT 1,               N'<',            N'<<>'                        WHERE @from_chars LIKE N'%<%'
    UNION ALL SELECT 2,               N'>',            N'<>>'                        WHERE @from_chars LIKE N'%>%'
    UNION ALL SELECT 3,               N'<<<>>',        N'<<>'                        WHERE @from_chars LIKE N'%<%' AND @from_chars LIKE N'%>%'

    UNION ALL SELECT 3 + id,          string_from,    string_interim FROM dictionary WHERE string_from NOT IN (N'<', N'>')
    UNION ALL SELECT 3 + @steps + id, string_interim, string_to      FROM dictionary
  )
  SELECT
    @ReplaceTarget = REPLACE(@ReplaceTarget, string_from, string_to)
  FROM
    mapping_sequence
  ORDER BY
    id
  ;

  RETURN @ReplaceTarget;

END

http://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=9dbe7214ac4b5bb00060686cfaa879c2"一个>

http://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=9dbe7214ac4b5bb00060686cfaa879c2


上述可能的小优化(尽可能减少 REPLACE 调用的次数)...

A possible minor optimisation of the above (To reduce the number of REPLACE calls where possible)...

CREATE FUNCTION dbo.Translate(
  @ReplaceTarget NVARCHAR(MAX),
  @from_chars    NVARCHAR(MAX),
  @to_chars      NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN

  DECLARE
    @steps INT = LEN('_' + @from_chars + '_') - 2
  ;

  WITH
    dictionary AS
  (
    SELECT
      id, string_from, string_to
    FROM
    (
      SELECT
        ROW_NUMBER() OVER (    ORDER BY string_from            )  AS id,
        ROW_NUMBER() OVER (PARTITION BY string_from ORDER BY id)  AS occurence,
        string_from,
        string_to
      FROM
        numbers
      CROSS APPLY
      (
        SELECT
          CAST(SUBSTRING(@from_chars, numbers.id, 1) AS NVARCHAR(5))  AS string_from,
          CAST(SUBSTRING(@to_chars,   numbers.id, 1) AS NVARCHAR(5))  AS string_to
      )
        chars
      WHERE
            numbers.id >  0
        AND numbers.id <= @steps
    )
      sorted_dictionary
    WHERE
      occurence = 1
  ),
    two_stage AS
  (
    SELECT
      map.*
    FROM
      dictionary   dict
    CROSS APPLY
    (
      SELECT COUNT(*) FROM dictionary WHERE dictionary.id > dict.id AND dictionary.string_from = dict.string_to
    )
      remap(hits)
    CROSS APPLY
    (
      SELECT id,                     dict.string_from,               dict.string_to          WHERE remap.hits = 0 AND dict.string_from NOT IN (N'<', N'>')
      UNION ALL
      SELECT id,                     dict.string_from,        N'<' + dict.string_from + N'>' WHERE remap.hits > 0 AND dict.string_from NOT IN (N'<', N'>')
      UNION ALL
      SELECT id + @steps,     N'<' + dict.string_from + N'>',        dict.string_to          WHERE remap.hits > 0 AND dict.string_from NOT IN (N'<', N'>')
      UNION ALL
      SELECT id + @steps * 2, N'<' + dict.string_from + N'>',        dict.string_to          WHERE                    dict.string_from     IN (N'<', N'>')
    )
      map
  )
  ,
    mapping_sequence(id, string_from, string_to) AS
  (
              SELECT 1,               N'<',          N'<<>'                   WHERE @from_chars LIKE N'%<%'
    UNION ALL SELECT 2,               N'>',          N'<>>'                   WHERE @from_chars LIKE N'%>%'
    UNION ALL SELECT 3,               N'<<<>>',      N'<<>'                   WHERE @from_chars LIKE N'%<%' AND @from_chars LIKE N'%>%'

    UNION ALL SELECT 3 + id,          string_from,   string_to FROM two_stage
  )
  SELECT
    @ReplaceTarget = REPLACE(@ReplaceTarget, string_from, string_to)
  FROM
    mapping_sequence
  ORDER BY
    id
  ;

  RETURN @ReplaceTarget;

END

http://dbfiddle.uk/?rdbms=sqlserver_20172017&fiddle=8af6ae050dc8d425521ae911b70a7968一个>

http://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=8af6ae050dc8d425521ae911b70a7968

或者...

http://dbfiddle.uk/?rdbms=sqlserver_201618150401704017040170404015dbfiddle.uk/一个>

http://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=1451aa88780463b1e7cfe15dd0071194

或者...

http://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=3079d4dd4289e8696072f6ee37be76ae"一个>

http://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=3079d4dd4289e8696072f6ee37be76ae

这篇关于SQL SERVER 中的 TRANSLATE 函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!