web-dev-qa-db-ja.com

空白を削除(スペース、タブ、改行)

私はSQL Server 2014を使用していて、列のコンテンツの最初と最後から空白を削除する必要があります。空白は、単純なスペース、タブ、または改行(両方\nおよび\r\n);例えば.

'    this content    '                          should become 'this content'
'  \r\n   \t\t\t this \r\n content \t  \r\n   ' should become 'this \r\n content'

等々。

私は最初のケースのみを達成することができました

UPDATE table t SET t.column = LTRIM(RTRIM(t.column))

それ以外の場合は機能しません。

10
Giovanni Lovato

SQL Server 2017以降を使用しているユーザー向け

[〜#〜] trim [〜#〜] 組み込み関数を使用できます。例えば:

_DECLARE @Test NVARCHAR(4000);
SET @Test = N'  
    ' + NCHAR(0x09) + N'  ' + NCHAR(0x09) + N' this 
 ' + NCHAR(0x09) + NCHAR(0x09) + N'  content' + NCHAR(0x09) + NCHAR(0x09) + N'  
' + NCHAR(0x09) + N' ' + NCHAR(0x09) + NCHAR(0x09) + N'     ';

SELECT N'~'
        + TRIM(NCHAR(0x09) + NCHAR(0x20) + NCHAR(0x0D) + NCHAR(0x0A) FROM @Test)
        + N'~';
_

TRIMのデフォルトの動作はスペースのみを削除することです。そのため、タブと改行(CR + LF)も削除するには、_characters FROM_句を指定する必要があります。

また、_@Test_変数のタブ文字にNCHAR(0x09)を使用して、サンプルコードをコピーアンドペーストし、正しい文字を保持できるようにしました。それ以外の場合、このページがレンダリングされるときにタブはスペースに変換されます。

SQL Server 2016以前を使用している人向け

関数は、SQLCLRスカラーUDFまたはT-SQLインラインTVF(iTVF)として作成できます。 T-SQLインラインTVFは次のようになります。

_CREATE
--ALTER
FUNCTION dbo.TrimChars(@OriginalString NVARCHAR(4000), @CharsToTrim NVARCHAR(50))
RETURNS TABLE
WITH SCHEMABINDING
AS RETURN
WITH cte AS
(
  SELECT PATINDEX(N'%[^' + @CharsToTrim + N']%', @OriginalString) AS [FirstChar],
         PATINDEX(N'%[^' + @CharsToTrim + N']%', REVERSE(@OriginalString)) AS [LastChar],
        LEN(@OriginalString + N'~') - 1 AS [ActualLength]
)
SELECT cte.[ActualLength],
       [FirstChar],
       ((cte.[ActualLength] - [LastChar]) + 1) AS [LastChar],
       SUBSTRING(@OriginalString, [FirstChar],
                 ((cte.[ActualLength] - [LastChar]) - [FirstChar] + 2)) AS [FixedString]
FROM   cte;
GO
_

次のように実行します。

_DECLARE @Test NVARCHAR(4000);
SET @Test = N'  
    ' + NCHAR(0x09) + N'  ' + NCHAR(0x09) + N' this 
 ' + NCHAR(0x09) + NCHAR(0x09) + N'  content' + NCHAR(0x09) + NCHAR(0x09) + N'  
' + NCHAR(0x09) + N' ' + NCHAR(0x09) + NCHAR(0x09) + N'     ';

SELECT N'~' + tc.[FixedString] + N'~' AS [proof]
FROM   dbo.TrimChars(@Test, NCHAR(0x09) + NCHAR(0x20) + NCHAR(0x0D) + NCHAR(0x0A)) tc;
_

戻り値:

_proof
----
~this 
              content~
_

そして、_CROSS APPLY_を使用してUPDATEでそれを使用できます。

_UPDATE tbl
SET    tbl.[Column] = itvf.[FixedString]
FROM   SchemaName.TableName tbl
CROSS APPLY  dbo.TrimChars(tbl.[Column],
                           NCHAR(0x09) + NCHAR(0x20) + NCHAR(0x0D) + NCHAR(0x0A)) itvf
_

冒頭で述べたように、.NETにはTrim()メソッドが含まれているため、必要な操作を正確に実行できるので、SQLCLRを使用するのも簡単です。独自にコーディングしてSqlString.Value.Trim()を呼び出すか、無料バージョンの SQL# ライブラリをインストールできます(私が作成したものですが、この関数は無料バージョンに含まれています)。そして、String_Trim(これは空白のみを実行します)またはString_TrimCharsのいずれかを使用しますキャラクターを渡して両側からトリミングします(上記のiTVFと同じです)。

_DECLARE @Test NVARCHAR(4000);
SET @Test = N'  
    ' + NCHAR(0x09) + N'  ' + NCHAR(0x09) + N' this 
 ' + NCHAR(0x09) + NCHAR(0x09) + N'  content' + NCHAR(0x09) + NCHAR(0x09) + N'  
' + NCHAR(0x09) + N' ' + NCHAR(0x09) + NCHAR(0x09) + N'     ';

SELECT N'~' + SQL#.String_Trim(@Test) + N'~' AS [proof];
_

また、上記のiTVFの出力例とまったく同じ文字列を返します。しかし、スカラーUDFであるため、UPDATEで次のように使用します。

_UPDATE tbl
SET    tbl.[Column] = SQL#.String_Trim(itvf.[Column])
FROM   SchemaName.TableName tbl
_

上記のいずれも、数百万行にわたって使用する場合に効率的です。インラインTVFは、マルチステートメントTVFやT-SQLスカラーUDFとは異なり、最適化できます。また、SQLCLRスカラーUDFは、_IsDeterministic=true_としてマークされ、どちらのタイプのDataAccessもRead(ユーザーとシステムの両方のデフォルト)に設定しない限り、並列プランで使用される可能性があります。データアクセスはNone)であり、これらの条件は両方とも、上記の両方のSQLCLR関数に当てはまります。

8
Solomon Rutzky

TVF(テーブル値関数)を使用して、問題のある文字をデータの先頭と末尾から削除することを検討してください。

テストデータを保持するテーブルを作成します。

IF COALESCE(OBJECT_ID('dbo.TrimTest'), 0) <> 0
BEGIN
    DROP TABLE dbo.TrimTest;
END
CREATE TABLE dbo.TrimTest
(
    SampleData VARCHAR(50) NOT NULL
);

INSERT INTO dbo.TrimTest (SampleData)
SELECT CHAR(13) + CHAR(10) + CHAR(9) + 'this is ' + CHAR(13) + CHAR(10) + ' a test' + CHAR(13) + CHAR(10);
GO

TVFを作成します。

IF COALESCE(OBJECT_ID('dbo.StripCrLfTab'), 0) <> 0
BEGIN
    DROP FUNCTION dbo.StripCrLfTab;
END
GO
CREATE FUNCTION dbo.StripCrLfTab
(
    @val NVARCHAR(1000)
)
RETURNS @Results TABLE
(
    TrimmedVal NVARCHAR(1000) NULL
)
AS
BEGIN
    DECLARE @TrimmedVal NVARCHAR(1000);
    SET @TrimmedVal = CASE WHEN RIGHT(@val, 1) = CHAR(13) OR RIGHT(@val, 1) = CHAR(10) OR RIGHT(@val, 1) = CHAR(9)
            THEN LEFT(
                CASE WHEN LEFT(@val, 1) = CHAR(13) OR LEFT(@val, 1) = CHAR(10) OR LEFT(@val, 1) = CHAR(9)
                THEN RIGHT(@val, LEN(@val) - 1)
                ELSE @val
                END
                , LEN(@val) -1 )
            ELSE
                CASE WHEN LEFT(@val, 1) = CHAR(13) OR LEFT(@val, 1) = CHAR(10) OR LEFT(@val, 1) = CHAR(9)
                THEN RIGHT(@val, LEN(@val) - 1)
                ELSE @val
                END
            END;
    IF @TrimmedVal LIKE (CHAR(13) + '%')
        OR @TrimmedVal LIKE (CHAR(10) + '%')
        OR @TrimmedVal LIKE (CHAR(9) + '%')
        OR @TrimmedVal LIKE ('%' + CHAR(13))
        OR @TrimmedVal LIKE ('%' + CHAR(10))
        OR @TrimmedVal LIKE ('%' + CHAR(9))
        SELECT @TrimmedVal = tv.TrimmedVal
        FROM dbo.StripCrLfTab(@TrimmedVal) tv;
    INSERT INTO @Results (TrimmedVal)
    VALUES (@TrimmedVal);
    RETURN;
END;
GO

TVFを実行して結果を表示します。

SELECT tt.SampleData
    , stt.TrimmedVal
FROM dbo.TrimTest tt
CROSS APPLY dbo.StripCrLfTab(tt.SampleData) stt;

結果:

enter image description here

TVFは、関数に渡される文字列の最初と最後に問題のある文字がなくなるまで、自分自身を再帰的に呼び出します。これは多数の行でうまく機能する可能性は低いですが、データベースに挿入されるときにこれを使用してデータを修正する場合はおそらく問題なく動作します。

これをupdateステートメントで使用できます。

UPDATE dbo.TrimTest
SET TrimTest.SampleData = stt.TrimmedVal
FROM dbo.TrimTest tt
CROSS APPLY dbo.StripCrLfTab(tt.SampleData) stt;


SELECT *
FROM dbo.TrimTest;

結果(テキストとして):

enter image description here

4
Max Vernon

私はこの特定の状況で問題が発生しました。空白を含むすべてのフィールドを見つけてクリーンアップする必要がありましたが、データベースフィールドで4種類の可能な空白を見つけました(ASCIIコードテーブルへの参照):

  • 水平タブ(char(9))
  • 改行(char(10))
  • 垂直タブ(char(9))
  • スペース(char(32))

多分このクエリはあなたを助けることができます。

UPDATE @TABLE SET @COLUMN = replace(replace(replace(replace(@COLUMN,CHAR(9),''),CHAR(10),''),CHAR(13),''),CHAR(32),'')
1
sami.almasagedi