2016-12-10 14 views
-2

SQL Server:パラメータに基づいて文字列から特定の文字を削除する関数を作成します。SQL Server文字列から特定の文字を削除します。

  • パラメーター1は
  • パラメーター2、元の文字列である文字は、例えば

元の文字列から削除したいされています

call MyRemoveFunc('32.87.65.54.89', '87.65') -- this will return '32.54.89' 
call MyRemoveFunc('11.23.45', '23') -- this will return '11.45' 
call MyRemoveFunc('14.99.16.84', '84.14') -- this will return '99.16' 
call MyRemoveFunc('11.23.45.65.31.90', '23') -- this will return 11.45.65.31.90 

call MyRemoveFunc('34.35.36', '35') -- this will return 34.36 

call MyRemoveFunc('34.35.36.76.44.22', '35') -- this will return 34.36.76.44.22 

call MyRemoveFunc('34', '34') -- this will return blank 

call MyRemoveFunc('45.23.11', '45.11') -- this will return 23 

ここおかげ

+1

(HTTP [ここ]良い質問を書き込む方法を確認してください: //stackoverflow.com/help/how-to-ask)!このページの詳細を編集してこの質問を編集すると、探している回答を得るのに役立ちます。 –

+0

あなたは 'myRemoveFunc('34 .35.36.76.44.22 '、' 35 ')の呼び出し結果を取得する方法を教えてください - これは34.36を返す' – Squirrel

+0

あなたはどのバージョンのSQL Serverを使用していますか? – DarkKnight

答えて

1

Recursive CTEを使用して一つの方法であるとSplit string機能

;WITH data 
    AS (SELECT org_string, 
       replace_with, 
       cs.Item, 
       cs.ItemNumber 
     FROM (VALUES ('32.87.65.54.89','87.65'), 
         ('11.23.45','23'), 
         ('14.99.16.84','84.14'), 
         ('11.23.45.65.31.90','23'), 
         ('34.35.36','35'), 
         ('34.35.36.76.44.22','35'), 
         ('34','34'), 
         ('45.23.11','45.11')) tc (org_string, replace_with) 
       CROSS apply [Delimitedsplit8k](replace_with, '.') cs), 
    cte 
    AS (SELECT org_string, 
       replace_with, 
       Item, 
       Replace('.' + org_string, + '.' + Item, '') AS result, 
       ItemNumber 
     FROM data 
     WHERE ItemNumber = 1 
     UNION ALL 
     SELECT d.org_string, 
       d.replace_with, 
       d.Item, 
       CASE 
        WHEN LEFT(Replace('.' + result, '.' + d.Item, ''), 1) = '.' THEN Stuff(Replace('.' + result, '.' + d.Item, ''), 1, 1, '') 
        ELSE Replace('.' + result, '.' + d.Item, '') 
       END, 
       d.ItemNumber 
     FROM cte c 
       JOIN data d 
        ON c.org_string = d.org_string 
        AND d.ItemNumber = c.ItemNumber + 1) 
SELECT TOP 1 WITH ties org_string, 
         replace_with, 
         result = Isnull(Stuff(result, 1, 1, ''), '') 
FROM cte 
ORDER BY Row_number()OVER(partition BY org_string ORDER BY ItemNumber DESC) 

結果:

╔═══════════════════╦══════════════╦════════════════╗ 
║ org_string  ║ replace_with ║  result  ║ 
╠═══════════════════╬══════════════╬════════════════╣ 
║ 11.23.45   ║ 23   ║ 11.45   ║ 
║ 11.23.45.65.31.90 ║ 23   ║ 11.45.65.31.90 ║ 
║ 14.99.16.84  ║ 84.14  ║ 99.16   ║ 
║ 34    ║ 34   ║    ║ 
║ 34.35.36   ║ 35   ║ 34.36   ║ 
║ 34.35.36.76.44.22 ║ 35   ║ 34.36.76.44.22 ║ 
║ 45.23.11   ║ 45.11  ║ 23    ║ 
║ 32.87.65.54.89 ║ 87.65  ║ 32.54.89  ║ 
╚═══════════════════╩══════════════╩════════════════╝ 

上記のコードは、ユーザ定義関数に変換することができます。より多くのレコードがある場合は、スカラー関数の代わりにインラインテーブル値関数を作成することをお勧めします。

http://www.sqlservercentral.com/articles/Tally+Table/72993/

CREATE FUNCTION [dbo].[DelimitedSplit8K] 

     (@pString VARCHAR(8000), @pDelimiter CHAR(1)) 
RETURNS TABLE WITH SCHEMABINDING AS 
RETURN 
--===== "Inline" CTE Driven "Tally Table" produces values from 0 up to 10,000... 
    -- enough to cover NVARCHAR(4000) 
    WITH E1(N) AS (
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
       ),       --10E+1 or 10 rows 
     E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
     E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
cteTally(N) AS (--==== This provides the "base" CTE and limits the number of rows right up front 
        -- for both a performance gain and prevention of accidental "overruns" 
       SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
       ), 
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter) 
       SELECT 1 UNION ALL 
       SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter 
       ), 
cteLen(N1,L1) AS(--==== Return start and length (for use in substring) 
       SELECT s.N1, 
         ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000) 
        FROM cteStart s 
       ) 
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found. 
SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1), 
     Item  = SUBSTRING(@pString, l.N1, l.L1) 
    FROM cteLen l 
; 
GO 
+0

これは単純な置き換えではありません。 'Call MyRemoveFunc('14 .99.16.84 '、' 84.14 ')を返します - これは'99 .16'を返します – Squirrel

+0

@Squirrel - updated ... –

+0

@Prdp を選択dbo.Udf_string_replace('45 .23.11 '、' 45.11 ' ) - return 11.45.23これは間違っています corrctは返り値 '23' – Bas

0

から呼ばスプリット文字列関数のコードあなたはこれを試みることができる。..

CREATE FUNCTION StringSpecialReplace(@TargetString VARCHAR(1000), 
            @InputString VARCHAR(1000)) 
returns VARCHAR(1000) 
AS 
    BEGIN 

    declare @result as varchar(1000) 

    ;with CTE1 AS 
    (
     SELECT LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS Certs 
     FROM (SELECT CAST('<XMLRoot><RowData>' + REPLACE(@TargetString,'.','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x)t 
     CROSS APPLY x.nodes('/XMLRoot/RowData')m(n) 
    ), 
    CTE2 AS 
    (
     SELECT LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS Certs 
     FROM (SELECT CAST('<XMLRoot><RowData>' + REPLACE(@InputString,'.','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x)t 
     CROSS APPLY x.nodes('/XMLRoot/RowData')m(n) 
    ) 

    SELECT 
     @Result = CASE 
      WHEN @Result IS NULL 
      THEN certs 
      ELSE @Result + '.' + certs 
     END 
    FROM CTE1 where certs not in (select certs from CTE2) 

    return @Result 
END 
+0

thanks @DarkKnight .... iしようとします 。リプレイ – Bas

0
CREATE FUNCTION MyRemoveFunc (
      @OrigString VARCHAR(8000), 
      @RemovedString VARCHAR(max) 
      ) 
    RETURNS varchar(max) 
    BEGIN 

      DECLARE @xml XML 
      SET @xml='<n>'+REPLACE(@RemovedString,'.','</n><n>')+'</n>' 
      SET @OrigString='.'[email protected]+'.' 
      SELECT @OrigString=REPLACE(@OrigString,'.'+s.b.value('.','varchar(200)')+'.','.') 
      FROM @xml.nodes('n')s(b) 
      RETURN CASE WHEN LEN(@OrigString)>2 THEN SUBSTRING(@OrigString,2,LEN(@OrigString)-2) ELSE '' END 

    END 


    SELECT t.*,dbo.MyRemoveFunc(t.o,t.r) 
    FROM (VALUES ('32.87.65.54.89','87.65'), 
          ('11.23.45','23'), 
          ('14.99.16.84','84.14'), 
          ('11.23.45.65.31.90','23'), 
          ('34.35.36','35'), 
          ('34.35.36.76.44.22','35'), 
          ('34','34'), 
          ('45.23.11','45.11')) t (o, r) 
 
o     r  
----------------- ----- ------------------------- 
32.87.65.54.89 87.65 32.54.89 
11.23.45   23 11.45 
14.99.16.84  84.14 99.16 
11.23.45.65.31.90 23 11.45.65.31.90 
34.35.36   35 34.36 
34.35.36.76.44.22 35 34.36.76.44.22 
34    34  
45.23.11   45.11 23 
関連する問題