SQL Server - использование DATALENGTH в случае, где предложение вызывает ошибку усечения - PullRequest
1 голос
/ 08 ноября 2019

Я нашел сценарий, где у меня есть временная таблица со столбцом varchar(20), и я хочу проверить длину строки при ее обновлении.

CREATE TABLE #tmpTest
(
    code1 VARCHAR(20)
)

Этот код вызывает

, данные будут усечены

Ошибка:

DECLARE @CODE VARCHAR(10) = '0123456789';

UPDATE #tmpTest
SET code1 = '0123456789' + '/' + @CODE -- 21 chars
WHERE DATALENGTH('0123456789' + '/' + @CODE) <= 20;

Принимая во внимание:

DECLARE @CODE VARCHAR(10) = '0123456789';

IF DATALENGTH('0123456789' + '/' + @CODE) <= 20
BEGIN
    UPDATE #tmpTest
    SET code1 = '0123456789' + '/' + @CODE -- 21 chars
END

и

DECLARE @CODE VARCHAR(10) = '0123456789';

UPDATE #tmpTest
SET code1 = CASE 
              WHEN DATALENGTH('0123456789' + '/' + @CODE) <= 20  
                THEN '0123456789' + '/' + @CODE 
            END

Не выбрасывайте эту ошибку.

Мне любопытно понять, почему это происходит. Это связано с компилятором / оптимизатором, или я что-то не так делаю?

Ответы [ 2 ]

1 голос
/ 08 ноября 2019

Ошибка возникает даже в том случае, если таблица пуста, и в плане нет строк, проходящих через план. Это связано с тем, что (в первом случае) выражение оценивается заранее во время инициализации выполнения оператора.

Стек вызовов для исключения ниже

enter image description here

Во втором случае оператор никогда не выполняется вообще. В третьем случае результат CASE не превышает 20 символов, поэтому не вызывает проблем, даже если он вычисляется во время инициализации выполнения.

0 голосов
/ 08 ноября 2019

Ошибка первого запроса очень ясна: поле недостаточно для сохранения обновленного значения.

Ошибка, строка или двоичные данные будут обрезаны при попытке вставить

Второй и третий запросы не соответствуют условию, поэтому они не работают. Если вы выполните следующий запрос, вы увидите ОБНОВЛЕНИЕ НЕ РАБОТАЕТ

CREATE TABLE #tmpTest
(
  code1 VARCHAR(20)
)

INSERT INTO #tmpTest VALUES('0123456789')
DECLARE @CODE VARCHAR(10) = '0123456789';

    IF DATALENGTH('0123456789' + '/' + @CODE) <= 20
      BEGIN
        UPDATE #tmpTest
        SET code1 = '0123456789' + '/' + @CODE -- 21 chars
        PRINT 'UPDATE IS WORK'
        END
        ELSE
        BEGIN
        PRINT 'UPDATE IS NOT WORK'
      END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...