web-dev-qa-db-ja.com

SQL先頭または末尾のキャリッジリターンのみを削除

この質問はまだ意味のある質問がされていないことに私は驚いた。文字列の先頭または末尾でのみ、キャリッジリターンとラインフィード用のLTRIMRTRIMなどのSQLで同等の関数を作成するにはどうすればよいですか。

明らかにREPLACE(REPLACE(@MyString,char(10),''),char(13),'')は、すべてのキャリッジリターンと改行を削除します。これは私が探しているものではありません。先行または後続のものを削除したいだけです。

21
dynamphorous

notCHAR(13)またはCHAR(10)である最初の文字を見つけ、文字列の長さからその位置を減算します。

LTRIM()

SELECT RIGHT(@MyString,LEN(@MyString)-PATINDEX('%[^'+CHAR(13)+CHAR(10)+']%',@MyString)+1)

RTRIM()

SELECT LEFT(@MyString,LEN(@MyString)-PATINDEX('%[^'+CHAR(13)+CHAR(10)+']%',REVERSE(@MyString))+1)
27
Anon

次の関数は、使用可能なtrim関数の拡張タイプです。 sqlauthority.com からコピー

これらの関数は、末尾のスペース、先頭のスペース、空白、タブ、キャリッジリターン、ラインフィードなどを削除します。

左トリム

CREATE FUNCTION dbo.LTrimX(@str VARCHAR(MAX)) RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @trimchars VARCHAR(10)
SET @trimchars = CHAR(9)+CHAR(10)+CHAR(13)+CHAR(32)
IF @str LIKE '[' + @trimchars + ']%' SET @str = SUBSTRING(@str, PATINDEX('%[^' + @trimchars + ']%', @str), 8000)
RETURN @str
END

トリム右

CREATE FUNCTION dbo.RTrimX(@str VARCHAR(MAX)) RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @trimchars VARCHAR(10)
SET @trimchars = CHAR(9)+CHAR(10)+CHAR(13)+CHAR(32)
IF @str LIKE '%[' + @trimchars + ']'
SET @str = REVERSE(dbo.LTrimX(REVERSE(@str)))
RETURN @str
END

左と右の両方をトリムする

CREATE FUNCTION dbo.TrimX(@str VARCHAR(MAX)) RETURNS VARCHAR(MAX)
AS
BEGIN
RETURN dbo.LTrimX(dbo.RTrimX(@str))
END

関数の使用

SELECT dbo.TRIMX(@MyString)
9
sqluser

実行できる例を次に示します。

結果をXml値としてキャストすることにしたので、クリックするとキャリッジリターンを表示できるようになります。

DECLARE @CRLF Char(2) = (CHAR(0x0D) + CHAR(0x0A))
DECLARE @String VarChar(MAX) = @CRLF + @CRLF + '    Hello' + @CRLF + 'World  ' + @CRLF + @CRLF
--Unmodified String:
SELECT CAST(@String as Xml)[Unmodified]
--Remove Trailing Whitespace (including Spaces).
SELECT CAST(LEFT(@String, LEN(REPLACE(@String, @CRLF, '  '))) as Xml)[RemoveTrailingWhitespace]
--Remove Leading Whitespace (including Spaces).
SELECT CAST(RIGHT(@String, LEN(REVERSE(REPLACE(@String, @CRLF, '  ')))) as Xml)[RemoveLeadingWhitespace]
--Remove Leading & Trailing Whitespace (including Spaces).
SELECT CAST(SUBSTRING(@String, LEN(REPLACE(@String, ' ', '_')) - LEN(REVERSE(REPLACE(@String, @CRLF, '  '))) + 1, LEN(LTRIM(RTRIM(REPLACE(@String, @CRLF, '  '))))) as Xml)[RemoveAllWhitespace]
--Remove Only Leading and Trailing CR/LF's (while still preserving all other Whitespace - including Spaces). - 04/06/2016 - MCR.
SELECT CAST(SUBSTRING(@String, PATINDEX('%[^'+CHAR(13)+CHAR(10)+']%',@String), LEN(REPLACE(@String, ' ', '_')) - PATINDEX('%[^'+CHAR(13)+CHAR(10)+']%',@String) + 1 - PATINDEX('%[^'+CHAR(13)+CHAR(10)+']%', REVERSE(@String)) + 1) as Xml)[RemoveLeadingAndTrailingCRLFsOnly]

Cast-to-Xmlを削除することを忘れないでください。これは、概念実証として機能していることを示しているためです。

これは、現在受け入れられている回答よりも優れていますか?

一見すると、これは受け入れられた回答よりも多くの関数を使用しているように見えるかもしれません。
ただし、そうではありません。
受け入れられた回答にリストされている両方のアプローチを組み合わせた場合(both末尾と先頭の空白を削除するため)、レコードを更新する2つのパスを作成する必要がありますまたは 1つのロジックのすべてを別のロジックにコピーします(どこでも@Stringがリストされています)、これはより多くの関数呼び出しを引き起こし、さらに読みにくくなります。

3
MikeTeeVee

SQL Server 2017では、 TRIM 関数を使用して、先頭と末尾から特定の文字を一度に削除できます。

WITH testdata(str) AS (
    SELECT CHAR(13) + CHAR(10) + ' test ' + CHAR(13) + CHAR(10)
)
SELECT
    str,
    TRIM(CHAR(13) + CHAR(10) + CHAR(9) + ' ' FROM str) AS [trim cr/lf/tab/space],
    TRIM(CHAR(13) + CHAR(10) FROM str) AS [trim cr/lf],
    TRIM(' ' FROM str) AS [trim space]
FROM testdata

結果:

+----------------+---------------------+------------+----------------+
|str             |trim cr/lf/tab/space |trim cr/lf  |trim space      |
+----------------+---------------------+------------+----------------+
|␍␊␠test␠␍␊ |test                 |␠test␠    |␍␊␠test␠␍␊ |
+----------------+---------------------+------------+----------------+

最後の例(スペースのトリミング)は、期待どおりには何もしません。

1
Salman A