У меня есть следующая тестовая таблица в 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
Когда я пытаюсь найти длину TestField с помощью функции SQL Server LEN (), она не учитывает конечные пробелы, например:
-- 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
Как мне включить конечные пробелы в результат длины?
sql-server
Джейсон Снелдерс
источник
источник
Ответы:
Это четко задокументировано 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 - который «возвращает количество байт , используемый для представления любого выражения».
Пример:
источник
DATALENGTH
Вам также необходимо разделить результат на 2, если тестируемое выражение является типом широких символов (Unicode; nchar, nvarchar или ntext), поскольку результат выражается в байтах , а не в символах .varchar
и т.д. это может быть зависимым от сопоставления, и даже прямое деление на 2 не является надежным. См. Пример здесьLEN(REPLACE(expr, ' ', '_'))
. Это должно работать со строкамиvarchar
иnvarchar
и, содержащими специальные управляющие символы Юникода.DATALENGTH()
не следует рассматривать как альтернативный способ подсчета символов, поскольку он считает байты вместо символов, и это имеет значение при представлении той же строки вVARCHAR
/NVARCHAR
.Вы можете использовать этот трюк:
LEN (Str + 'x') - 1
источник
Я использую такой способ:
Я предпочитаю DATALENGTH, потому что это работает с разными типами данных, и я предпочитаю добавлять символ в конец, потому что вам не нужно беспокоиться о граничном случае, когда ваша строка уже имеет максимальную длину.
Примечание. Я бы проверил производительность перед тем, как использовать ее на очень большом наборе данных; хотя я только что протестировал его на 2M строках, и он был не медленнее, чем LEN без REPLACE ...
источник
Вы можете попросить кого-нибудь отправить запрос на расширение 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
Решение еще хуже , начиная с SQL Server 2012, так как он теперь поддерживает суррогатные пары в UTF-16, то есть персонаж может использовать до 4 байт. Пришло время исправить этуlen
функцию для соответствия ANSI или, по крайней мере, предоставить специальную функцию для подсчета символов, включая конечные пробелы.Есть проблемы с двумя ответами, получившими наибольшее количество голосов. Рекомендуемый ответ
DATALENGTH
подвержен ошибкам программиста. РезультатDATALENGTH
должен быть разделен на 2 дляNVARCHAR
типов, но не дляVARCHAR
типов. Это требует знания типа, длина которого вы получаете, и если этот тип изменится, вам придется старательно менять места, которые вы использовалиDATALENGTH
.Также существует проблема с ответом, получившим наибольшее количество голосов (который, я признаю, был моим предпочтительным способом сделать это, пока эта проблема не укусила меня). Если объект, который вы получаете длину, относится к типу
NVARCHAR(4000)
и фактически содержит строку из 4000 символов, SQL будет игнорировать добавленный символ, а не неявно приводить результат кNVARCHAR(MAX)
. Конечный результат - неправильная длина. То же самое произойдет с VARCHAR (8000).То, что я обнаружил, работает, почти так же быстро, как и обычное старое
LEN
, быстрее, чемLEN(@s + 'x') - 1
для больших строк, и не предполагает, что ширина основного символа следующая:Он получает длину данных, а затем делит ее на длину одного символа из строки. Добавление «x» охватывает случай, когда строка пуста (что в этом случае дает деление на ноль). Это работает независимо от того,
@s
есть лиVARCHAR
илиNVARCHAR
. ВыполнениеLEFT
1 символа перед добавлением сбрит некоторое время, когда строка большая. Однако проблема заключается в том, что он некорректно работает со строками, содержащими суррогатные пары.В комментарии к принятому ответу упоминается еще один способ, используя
REPLACE(@s,' ','x')
. Этот метод дает правильный ответ, но на пару порядков медленнее, чем другие методы, когда струна большая.Учитывая проблемы, возникающие при использовании суррогатных пар при использовании любого метода
DATALENGTH
, я считаю, что самый безопасный метод, который дает правильные ответы, о которых я знаю, это следующий:Это быстрее, чем
REPLACE
техника, и намного быстрее с более длинными струнами. По сути, это техникаLEN(@s + 'x') - 1
, но с защитой для крайнего случая, когда строка имеет длину 4000 (для nvarchar) или 8000 (для varchar), так что даже для этого дается правильный ответ. Он также должен правильно обрабатывать строки с суррогатными парами.источник
N'x𤭢x' COLLATE Latin1_General_100_CI_AS_SC
дает 4, аLEN
дает 3.Вам также необходимо убедиться, что ваши данные действительно сохранены с завершающими пробелами. Когда ANSI PADDING выключен (не по умолчанию):
источник
LEN по умолчанию обрезает конечные пробелы, поэтому я обнаружил, что это работает, когда вы перемещаете их на передний план.
(LEN (ОБРАТНЫЙ (TestField))
Так что, если бы вы хотели, вы могли бы сказать
Конечно, не используйте это для ведущих пробелов.
источник
declare @TestField varchar(10);
SET @TestField = ' abc '; -- Length with spaces is 5.
select LEN(REVERSE(@TestField)) -- Returns 4
select LEN(@TestField) -- Returns 4
Вы должны определить функцию CLR, которая возвращает поле длины строки, если вам не нравится объединение строк. Я использую
LEN('x' + @string + 'x') - 2
в своих производственных сценариях использования.источник
Если вам не нравится
DATALENGTH
из-за проблем с n / varchar, как насчет:что просто
с защитой от деления на ноль.
Разделив на DATALENGTH одного char, мы получаем нормализованную длину.
(Конечно, по-прежнему возникают проблемы с суррогатными парами, если это вызывает беспокойство.)
источник
используйте SELECT DATALENGTH ('строка')
источник