私は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))
それ以外の場合は機能しません。
[〜#〜] 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)
を使用して、サンプルコードをコピーアンドペーストし、正しい文字を保持できるようにしました。それ以外の場合、このページがレンダリングされるときにタブはスペースに変換されます。
関数は、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関数に当てはまります。
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;
結果:
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;
結果(テキストとして):
私はこの特定の状況で問題が発生しました。空白を含むすべてのフィールドを見つけてクリーンアップする必要がありましたが、データベースフィールドで4種類の可能な空白を見つけました(ASCIIコードテーブルへの参照):
多分このクエリはあなたを助けることができます。
UPDATE @TABLE SET @COLUMN = replace(replace(replace(replace(@COLUMN,CHAR(9),''),CHAR(10),''),CHAR(13),''),CHAR(32),'')