Programing

SQL Server에서 후행 공백을 포함하지 않는 LEN 함수

lottogame 2020. 8. 17. 09:29
반응형

SQL Server에서 후행 공백을 포함하지 않는 LEN 함수


SQL Server 2005에 다음 테스트 테이블이 있습니다.

CREATE TABLE [dbo].[TestTable]
(
 [ID] [int] NOT NULL,
 [TestField] [varchar](100) NOT NULL
) 

다음으로 채워짐 :

INSERT INTO TestTable (ID, TestField) VALUES (1, 'A value');   -- Len = 7
INSERT INTO TestTable (ID, TestField) VALUES (2, 'Another value      '); -- Len = 13 + 6 spaces

SQL Server LEN () 함수로 TestField의 길이를 찾으려고하면 후행 공백을 계산하지 않습니다. 예 :

-- Note: Also results the grid view of TestField do not show trailing spaces (SQL Server 2005).
SELECT 
 ID, 
 TestField, 
 LEN(TestField) As LenOfTestField, -- Does not include trailing spaces
FROM 
 TestTable

길이 결과에 후행 공백을 어떻게 포함합니까?


이것은 Microsoft가 MSDN의 http://msdn.microsoft.com/en-us/library/ms190329(SQL.90).aspx 에서 명확하게 문서화했으며 , LEN은 "지정된 문자열 표현식의 문자 수를 반환합니다. 후행 공백 ". 그러나 조심하지 않으면 놓치기 쉬운 세부 사항입니다.

대신 DATALENGTH 함수를 사용해야합니다. http://msdn.microsoft.com/en-us/library/ms173486(SQL.90).aspx 참조 - "모든 식을 나타내는 데 사용되는 바이트 수를 반환합니다".

예:

SELECT 
    ID, 
    TestField, 
    LEN(TestField) As LenOfTestField,           -- Does not include trailing spaces
    DATALENGTH(TestField) As DataLengthOfTestField      -- Shows the true length of data, including trailing spaces.
FROM 
    TestTable

이 트릭을 사용할 수 있습니다.

LEN (Str + 'x')-1


이 방법을 사용합니다.

LEN(REPLACE(TestField, ' ', '.'))

이것은 다른 데이터 유형에서 작동하기 때문에 DATALENGTH보다 선호하며 문자열이 이미 최대 길이에있는 경우에 대해 걱정할 필요가 없기 때문에 끝에 문자를 추가하는 것보다 선호합니다.

참고 : 매우 큰 데이터 세트에 대해 사용하기 전에 성능을 테스트합니다. 2M 행에 대해 테스트했지만 REPLACE 없이는 LEN보다 느리지 않았습니다.


"길이 결과에 후행 공백을 어떻게 포함합니까?"

여기에있는이 놀랍도록 간단한 문제에 대해 나열된 거의 모든 해결 방법에 결함이 있거나 비효율적이기 때문에 누군가 SQL Server 향상 요청 / 버그 보고서를 제출하게됩니다. 이것은 SQL Server 2012에서도 여전히 사실 인 것처럼 보입니다. 자동 트리밍 기능은 ANSI / ISO SQL-92에서 비롯된 것일 수 있지만 몇 가지 구멍이있는 것 같습니다 (또는 계산 부족).

여기에서 "LEN이 후행 공백을 계산하도록 설정 추가"에 투표하십시오.

https://feedback.azure.com/forums/908035-sql-server/suggestions/34673914-add-setting-so-len-counts-trailing-whitespace

폐기 된 연결 링크 : https://connect.microsoft.com/SQLServer/feedback/details/801381


두 개의 상위 투표 답변에 문제가 있습니다. 권장하는 대답 DATALENGTH은 프로그래머 오류가 발생하기 쉽습니다. 의 결과는 유형이 아닌 유형 DATALENGTH에 대해 2로 NVARCHAR나눠야 VARCHAR합니다. 이를 위해서는 길이를 얻고있는 유형에 대한 지식이 필요하며, 유형이 변경되면 사용한 장소를 부지런히 변경해야합니다 DATALENGTH.

또한 가장 많이 찬성 된 답변에도 문제가 있습니다 (이 문제가 나를 물릴 때까지 내가 선호하는 방법임을 인정합니다). 길이를 얻는 것이 유형 NVARCHAR(4000)이고 실제로 4000 자의 문자열을 포함하는 경우 SQL은 결과를 암시 적으로 캐스트하지 않고 추가 된 문자를 무시합니다 NVARCHAR(MAX). 최종 결과는 잘못된 길이입니다. VARCHAR (8000)에서도 같은 일이 발생합니다.

내가 찾은 것은 거의 평범한 오래된 것만 큼 빠르며 큰 문자열 LEN보다 빠르며 LEN(@s + 'x') - 1기본 문자 너비가 다음과 같다고 가정하지 않습니다.

DATALENGTH(@s) / DATALENGTH(LEFT(LEFT(@s, 1) + 'x', 1))

이것은 데이터 길이를 얻은 다음 문자열에서 단일 문자의 데이터 길이로 나눕니다. 'x'의 추가는 문자열이 비어있는 경우를 다룹니다 (이 경우 0으로 나누기). 이 여부를 작동 @s하다 VARCHAR거나 NVARCHAR. LEFT추가하기 전에 1 문자를 수행하면 문자열이 클 때 얼마 동안 면도됩니다. 하지만 문제는 서로 게이트 쌍을 포함하는 문자열에서 올바르게 작동하지 않는다는 것입니다.

There is another way mentioned in a comment to the accepted answer, using REPLACE(@s,' ','x'). That technique gives the correct answer, but is a couple orders of magnitude slower than the other techniques when the string is large.

Given the problems introduced by surrogate pairs on any technique that uses DATALENGTH, I think the safest method that gives correct answers that I know of is the following:

LEN(CONVERT(NVARCHAR(MAX), @s) + 'x') - 1

This is faster than the REPLACE technique, and much faster with longer strings. Basically this technique is the LEN(@s + 'x') - 1 technique, but with protection for the edge case where the string has a length of 4000 (for nvarchar) or 8000 (for varchar), so that the correct answer is given even for that. It also should handle strings with surrogate pairs correctly.


You need also to ensure that your data is actually saved with the trailing blanks. When ANSI PADDING is OFF (non-default):

Trailing blanks in character values inserted into a varchar column are trimmed.


LEN cuts trailing spaces by default, so I found this worked as you move them to the front

(LEN(REVERSE(TestField))

So if you wanted to, you could say

SELECT
t.TestField,
LEN(REVERSE(t.TestField)) AS [Reverse],
LEN(t.TestField) AS [Count]
FROM TestTable t
WHERE LEN(REVERSE(t.TestField)) <> LEN(t.TestField)

Don't use this for leading spaces of course.


You should define a CLR function that returns the String's Length field, if you dislike string concatination. I use LEN('x' + @string + 'x') - 2 in my production use-cases.


If you dislike the DATALENGTH because of of n/varchar concerns, how about:

select DATALENGTH(@var)/isnull(nullif(DATALENGTH(left(@var,1)),0),1)

which is just

select DATALENGTH(@var)/DATALENGTH(left(@var,1))

wrapped with divide-by-zero protection.

By dividing by the DATALENGTH of a single char, we get the length normalised.

(Of course, still issues with surrogate-pairs if that's a concern.)


use SELECT DATALENGTH('string ')

참고URL : https://stackoverflow.com/questions/2025585/len-function-not-including-trailing-spaces-in-sql-server

반응형