38

これは、Access SQL で複数の文字を置き換える方法と同様の質問に基づいています。

SQL Server 2005 では、replace() 関数が where 句内で 19 個の置換に制限されているように見えるため、これを書きました。

次のタスクがあります: 列で一致を実行する必要があり、replace() 関数を使用して複数の不要な文字を削除する一致の可能性を高める必要があります

DECLARE @es NVarChar(1) SET @es = ''
DECLARE @p0 NVarChar(1) SET @p0 = '!'
DECLARE @p1 NVarChar(1) SET @p1 = '@'
---etc...

SELECT *
FROM t1,t2 
WHERE  REPLACE(REPLACE(t1.stringkey,@p0, @es), @p1, @es) 
     = REPLACE(REPLACE(t2.stringkey,@p0, @es), @p1, @es)    
---etc 

その where 句に >19 個の REPLACE() がある場合、機能しません。したがって、私が思いついた解決策は、この例でtrimCharsという名前の SQL 関数を作成することです (@22 で開始してすみません)

CREATE FUNCTION [trimChars] (
   @string varchar(max)
) 

RETURNS varchar(max) 
AS
BEGIN

DECLARE @es NVarChar(1) SET @es = ''
DECLARE @p22 NVarChar(1) SET @p22 = '^'
DECLARE @p23 NVarChar(1) SET @p23 = '&'
DECLARE @p24 NVarChar(1) SET @p24 = '*'
DECLARE @p25 NVarChar(1) SET @p25 = '('
DECLARE @p26 NVarChar(1) SET @p26 = '_'
DECLARE @p27 NVarChar(1) SET @p27 = ')'
DECLARE @p28 NVarChar(1) SET @p28 = '`'
DECLARE @p29 NVarChar(1) SET @p29 = '~'
DECLARE @p30 NVarChar(1) SET @p30 = '{'

DECLARE @p31 NVarChar(1) SET @p31 = '}'
DECLARE @p32 NVarChar(1) SET @p32 = ' '
DECLARE @p33 NVarChar(1) SET @p33 = '['
DECLARE @p34 NVarChar(1) SET @p34 = '?'
DECLARE @p35 NVarChar(1) SET @p35 = ']'
DECLARE @p36 NVarChar(1) SET @p36 = '\'
DECLARE @p37 NVarChar(1) SET @p37 = '|'
DECLARE @p38 NVarChar(1) SET @p38 = '<'
DECLARE @p39 NVarChar(1) SET @p39 = '>'
DECLARE @p40 NVarChar(1) SET @p40 = '@'
DECLARE @p41 NVarChar(1) SET @p41 = '-'

return   REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
       @string, @p22, @es), @p23, @es), @p24, @es), @p25, @es), @p26, @es), @p27, @es), @p28, @es), @p29, @es), @p30, @es), @p31, @es), @p32, @es), @p33, @es), @p34, @es), @p35, @es), @p36, @es), @p37, @es), @p38, @es), @p39, @es), @p40, @es), @p41, @es)
END 

これは、他の置換文字列に加えて使用できます

SELECT *
FROM t1,t2 
WHERE  trimChars(REPLACE(REPLACE(t1.stringkey,@p0, @es), @p1, @es) 
         = REPLACE(REPLACE(t2.stringkey,@p0, @es), @p1, @es))   

同様の置換を行う関数をさらにいくつか作成しました。例えば、trimChars(trimMoreChars()

SELECT *
FROM t1,t2 
WHERE  trimChars(trimMoreChars(REPLACE(REPLACE(t1.stringkey,@p0, @es), @p1, @es) 
         = REPLACE(REPLACE(t2.stringkey,@p0, @es), @p1, @es)))

誰かがこの問題のパフォーマンスとよりクリーンな実装の点でより良い解決策を教えてくれますか?

4

12 に答える 12

5

スカラーユーザー定義関数を作成することをお勧めします。これは例です(変数名はスペイン語なので、事前に申し訳ありません):

CREATE FUNCTION [dbo].[Udf_ReplaceChars] (
  @cadena VARCHAR(500),  -- String to manipulate
  @caracteresElim VARCHAR(100),  -- String of characters to be replaced
  @caracteresReem VARCHAR(100)   -- String of characters for replacement
) 
RETURNS VARCHAR(500)
AS
BEGIN
  DECLARE @cadenaFinal VARCHAR(500), @longCad INT, @pos INT, @caracter CHAR(1), @posCarER INT;
  SELECT
    @cadenaFinal = '',
    @longCad = LEN(@cadena),
    @pos = 1;

  IF LEN(@caracteresElim)<>LEN(@caracteresReem)
    BEGIN
      RETURN NULL;
    END

  WHILE @pos <= @longCad
    BEGIN
      SELECT
        @caracter = SUBSTRING(@cadena,@pos,1),
        @pos = @pos + 1,
        @posCarER = CHARINDEX(@caracter,@caracteresElim);

      IF @posCarER <= 0
        BEGIN
          SET @cadenaFinal = @cadenaFinal + @caracter;
        END
      ELSE
        BEGIN
          SET @cadenaFinal = @cadenaFinal + SUBSTRING(@caracteresReem,@posCarER,1)
        END
    END

  RETURN @cadenaFinal;
END

この関数を使用した例を次に示します。

SELECT dbo.Udf_ReplaceChars('This is a test.','sat','Z47');

結果は次のとおりです。7hiZiZ47eZ7。

ご覧のとおり、パラメーターの各文字は、@caracteresElimパラメーターの同じ位置にある文字に置き換えられてい@caracteresReemます。

于 2013-01-18T20:57:17.123 に答える
0

1つのオプションは、数値/集計テーブルを使用して、疑似セットベースのクエリを介して反復プロセスを実行することです。

文字置換の一般的な考え方は、単純な文字コード表のアプローチで示すことができます。

create table charMap (srcChar char(1), replaceChar char(1))
insert charMap values ('a', 'z')
insert charMap values ('b', 'y')


create table testChar(srcChar char(1))
insert testChar values ('1')
insert testChar values ('a')
insert testChar values ('2')
insert testChar values ('b')

select 
coalesce(charMap.replaceChar, testChar.srcChar) as charData
from testChar left join charMap on testChar.srcChar = charMap.srcChar

次に、タリーテーブルアプローチを導入して、文字列内の各文字位置をルックアップできます。

create table tally (i int)
declare @i int
set @i = 1
while @i <= 256 begin
    insert tally values (@i)
    set @i = @i + 1
end

create table testData (testString char(10))
insert testData values ('123a456')
insert testData values ('123ab456')
insert testData values ('123b456')

select
    i,
    SUBSTRING(testString, i, 1) as srcChar,
    coalesce(charMap.replaceChar, SUBSTRING(testString, i, 1)) as charData
from testData cross join tally
    left join charMap on SUBSTRING(testString, i, 1) = charMap.srcChar
where i <= LEN(testString)
于 2009-10-16T20:46:27.713 に答える
0

Charles Bretana が彼の回答を削除した理由がわからないので、CW の回答として追加し直していますが、永続化された計算列は、ほぼ常にクレンジングまたは変換されたデータが必要なこれらのケースを処理するための非常に良い方法です。 、ただし、元のゴミを保存する必要があります。彼の提案は、データのクレンジング方法に関係なく、関連性があり適切です。

具体的には、私の現在のプロジェクトでは、先行ゼロと矛盾して格納されているいくつかの特定の数値識別子からすべての先行ゼロを削除する永続的な計算列があります (幸いなことに、これはストレート T-SQL で実際に簡単に処理されます)。これは、それを必要とするテーブルの永続的な計算列に格納され、インデックスが作成されます。これは、適合した識別子が結合でよく使用されるためです。

于 2009-10-17T02:58:29.623 に答える
0

これは非常に簡潔なSTRING_SPLITを使用した最新のソリューションです。欠点は、少なくとも互換性レベル 130 で実行されているバージョンの SQL Server 2016 が必要なことです。

Declare @strOriginal varchar(100) = 'Juliet ro><0zs my s0x()rz!!?!one!@!@!@!'
Declare @strModified varchar(100) = @strOriginal
Declare @disallowed  varchar(100) = '> < ( ) ! ? @'

Select 
   @strModified = Replace(@strModified, value, '') 
From 
   String_Split(@disallowed,' ')

Select @strModified

戻り値:

Juliet ro0zs my s0xrzone
于 2021-04-06T14:44:32.223 に答える