Почему LEN (char (32)) = 0 в T-SQL? - PullRequest
1 голос
/ 16 мая 2019

Я хотел написать функцию для подсчета количества разделителей или любой подстроки (которая может быть пробелом) в текстовой строке, выдавая хакерскую ошибку, если разделитель был нулевым или пустым:

if len(@lookfor)=0 or @lookfor is null return Cast('substring must not be null or empty' as int)

Но если функция вызывается с @lookfor = '', это отключает ошибку.

Мне известно о ДАННЫХ (). Просто любопытно, почему один пробел рассматривается как «трейлинг», если перед ним ничего нет.

Ответы [ 2 ]

3 голосов
/ 16 мая 2019

Мне известно о ДАННЫХ (). Просто любопытно, почему лечится одно место как "тянущийся", если перед ним ничего нет.

Это трейлинг, потому что он в конце строки. Это также ведущий, так как это в начале.

Но если функция вызывается с @lookfor = '', это отключает ошибку

То, что мешает многим людям использовать SQL, это то, как '' = ''; Обратите внимание на этот запрос:

DECLARE @blank VARCHAR(10) = '', @space VARCHAR(10) = CHAR(32);
SELECT CASE WHEN @blank = @space THEN 'That the...!?!?' END;

Вы можете изменить @space на CHAR (32) + CHAR (32) + .... и @space и @blank все равно будут равны.

Сложнее немного заметить, что DATALENGTH для пустого / пустого значения равно 0, когда это VARCHAR (N), но DATALENGTH равно N, когда для значений CHAR (N). Другими словами, SELECT DATALENGTH(CAST('' AS CHAR(1))) возвращает 1 и SELECT DATALENGTH(CAST('' AS CHAR(10))) возвращает 10.

Это означает, что если ваша переменная-разделитель скажет CHAR (1) - это запутает вас. Вот функция для вас:

CREATE FUNCTION dbo.CountDelimiters(@string VARCHAR(8000), @delimiter VARCHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS RETURN
SELECT DCount = MAX(DATALENGTH(@string)-LEN(REPLACE(@string,@delimiter,'')))
WHERE  DATALENGTH(@delimiter) > 0;

Обратите внимание, что @delimter - это VARCHAR (1), а NOT - тип данных CHAR.

Формула для подсчета разделителей в @string:

DATALENGTH(@string)-LEN(REPLACE(@string,@delimiter,'')) или

(DATALENGTH(@string)-LEN(REPLACE(@string,@delimiter,'')))/DATALENGTH(@delimiter) при работе с разделителями длиннее 1`.

WHERE DATALENGTH(@delimiter) > 0 заставит функцию игнорировать NULL или пустое значение. Это известно как Startup Predicate .

Установка MAX вокруг DATALENGTH(@string)-LEN(REPLACE(@string,@delimiter,'')) заставляет функцию возвращать значение NULL, если вы передаете ему пустое значение или значение NULL.

Это вернет 10 для количества пробелов в моей строке:

SELECT f.DCount FROM dbo.CountDelimiters('one space  two spaces   three   ', CHAR(32)) AS f;

Против таблицы вы бы использовали такую ​​функцию (обратите внимание, что я считаю количество раз, когда появляется буква "A":

-- Sample Strings
DECLARE @table TABLE (SomeText VARCHAR(36));
INSERT @table VALUES('ABCABC'),('XXX'),('AAA'),(''),(NULL);

SELECT      t.SomeText, f.DCount    
FROM        @table                               AS t
CROSS APPLY dbo.CountDelimiters(t.SomeText, 'A') AS f;

Что возвращает:

SomeText                             DCount
------------------------------------ -----------
ABCABC                               2
XXX                                  0
AAA                                  3
                                     0
NULL                                 NULL
1 голос
/ 17 мая 2019

Если в конце строки есть символ, он считается завершающим, даже если перед ним нет других символов.То же самое для логики в отношении начальных символов.

Так что ' ' можно считать пустой строкой (''), имеющей завершающий пробел.

Когда я начал использовать SQL, я также заметил поведениечто функция LEN игнорирует конечные пробелы.И я думаю (но я не уверен), что это связано с тем фактом, что LEN, вероятно, также должен вести себя «правильно» при использовании со значениями CHAR / NCHAR.В отличие от VARCHAR / NVARCHAR, значения CHAR / NCHAR имеют фиксированную ширину и будут автоматически заполняться конечными пробелами.Поэтому, если вы поместите значение 'abc' в поле / переменную типа CHAR (5), значение станет 'abc ', но функция LEN все равно будет «правильно» возвращать 3 в этом случае.

Iрассмотрим это как странную причуду SQL.

Примечание:

Функция DATALENGTH не будет игнорировать конечные пробелы в значениях VARCHAR / NVARCHAR.Но обратите внимание, что DATALENGTH вернет размер в байтах значения поля.Поэтому, если вы используете данные Unicode (NCHAR / NVARCHAR), функция DATALENGTH вернет 6 для значения N'abc', потому что каждый символ Unicode в SQL Server использует 2 байта!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...