1. ホーム
  2. sql-server

[解決済み] SQLのReplace関数内の正規表現?

2022-03-01 13:19:18

質問

SELECT REPLACE('<strong>100</strong><b>.00 GB', '%^(^-?\d*\.{0,1}\d+$)%', '');

数字の2つの部分の間のマークアップを上記の正規表現で置き換えたいのですが、うまくいかないようです。以下のような簡単なものを試したので、正規表現の構文がおかしいのかどうかはわかりません。 '%[^0-9]%' が、これもうまくいきません。どうすれば実現できるのか、どなたかご存知でしょうか?

解決方法は?

を使用することができます。 PATINDEX で、パターン(文字列)の出現する最初のインデックスを探します。次に STUFF を使えば、マッチしたパターン(文字列)に別の文字列を詰め込むことができます。

各行をループします。不正な文字を必要な文字に置き換えます。あなたの場合、数字以外を空白に置き換えます。内部ループは、現在のセルに複数の不正な文字がある場合、ループのことです。

DECLARE @counter int

SET @counter = 0

WHILE(@counter < (SELECT MAX(ID_COLUMN) FROM Table))
BEGIN  

    WHILE 1 = 1
    BEGIN
        DECLARE @RetVal varchar(50)

        SET @RetVal =  (SELECT Column = STUFF(Column, PATINDEX('%[^0-9.]%', Column),1, '')
        FROM Table
        WHERE ID_COLUMN = @counter)

        IF(@RetVal IS NOT NULL)       
          UPDATE Table SET
          Column = @RetVal
          WHERE ID_COLUMN = @counter
        ELSE
            break
    END

    SET @counter = @counter + 1
END

注意 しかし、これは遅いです! varcharカラムを持つことが影響する可能性があります。そのため、LTRIM RTRIM を使用すると、少しは楽になるかもしれません。とはいえ、遅いです。

Credit goes to これ StackOverFlowの回答です。

EDIT また、@srutzky にも謝意を表します。

編集 (@Tmdean) 一度に1つの行を行う代わりに、この回答はより集合ベースの解決策に適応させることができます。それでも1行に含まれる非数字の数の最大値を反復するので、理想的ではありませんが、ほとんどの状況で許容されるはずだと思います。

WHILE 1 = 1 BEGIN
    WITH q AS
        (SELECT ID_Column, PATINDEX('%[^0-9.]%', Column) AS n
        FROM Table)
    UPDATE Table
    SET Column = STUFF(Column, q.n, 1, '')
    FROM q
    WHERE Table.ID_Column = q.ID_Column AND q.n != 0;

    IF @@ROWCOUNT = 0 BREAK;
END;

また、テーブルの中に、そのフィールドがまだスクラビングされていないかどうかを示すビットカラムを保持しておくと、かなり効率が良くなります。(この例では、NULLは"Unknown"を表し、カラムのデフォルトとすべきです)。

DECLARE @done bit = 0;
WHILE @done = 0 BEGIN
    WITH q AS
        (SELECT ID_Column, PATINDEX('%[^0-9.]%', Column) AS n
        FROM Table
        WHERE COALESCE(Scrubbed_Column, 0) = 0)
    UPDATE Table
    SET Column = STUFF(Column, q.n, 1, ''),
        Scrubbed_Column = 0
    FROM q
    WHERE Table.ID_Column = q.ID_Column AND q.n != 0;

    IF @@ROWCOUNT = 0 SET @done = 1;

    -- if Scrubbed_Column is still NULL, then the PATINDEX
    -- must have given 0
    UPDATE table
    SET Scrubbed_Column = CASE
        WHEN Scrubbed_Column IS NULL THEN 1
        ELSE NULLIF(Scrubbed_Column, 0)
    END;
END;

スキーマを変更したくない場合は、中間結果をテーブル値変数に格納し、最後に実際のテーブルに適用するように簡単に適応できます。