SQL Server Вставка в - Как определить столбец, который вызывает ошибку усечения

11

У меня есть хранимая процедура, которая вставляет 650 полей в таблицу. Вставка не выполняется с ошибкой усечения.

Это просто

INSERT INTO
SELECT (a bunch of fields) 
FROM (a bunch of tables)

Ниже приведено сообщение об ошибке:

Сообщение 8152, уровень 16, состояние 14, процедура DSP_Procedure, строка 1075 Строка или двоичные данные будут обрезаны.

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

Тот факт, что оператор выбора для вставки в таблицу имеет 650 полей, затрудняет точное определение того, какое поле вызывает ошибку усечения.

Я думаю, что я могу, возможно, закомментировать блоки полей за один раз, чтобы SP вставлял только 100 полей за раз, а затем запускал SP 6 или 7 раз, пока я, по крайней мере, не смог сузить группу из 100 полей. это будет содержать поле, которое вызывает ошибку усечения.

В качестве альтернативы я думаю, что, возможно, я могу просто SELECT INTOсоздать новую таблицу, а затем сравнить длины данных в таблице с длинами данных целевой таблицы, в которую я пытаюсь вставить свой SP, чтобы увидеть, какое поле содержит длину, превышающую ожидаемую. ..

Я использую SQL Server 2014.

Есть ли более простые альтернативы?

Хуан Велес
источник
1
Я хотел бы перейти к INFORMATION_SCHEMA.COLUMNS и сравнить типы данных с теми, которые вы пытаетесь вставить. К сожалению, SQL-сервер не имеет динамических типов данных для объявления переменных, как ORACLE.
MguerraTorres
2
Я хотел бы использовать ваш второй вариант, вставить в новую (или #temp) таблицу, а затем сравнить длины столбцов. Или вы можете обернуть LEN () вокруг всех столбцов в select, а затем сделать внешний запрос, выполняющий MAX () для каждого ..., который даст вам наибольшую длину текста для полей. Конечно, это предполагает, что это поле типа char, которое доставляет вам проблемы. Не используете smalldatetime или tinyint?
Джонатан
1
Я бы пошел с подходом «Выбрать в» и сравнить длины столбцов, да. Может быть, с "WHERE 1 = 0", чтобы в таблице не было строк. Неудобно, если ваш SELECT не содержит уникальных имен для выбранных столбцов. Я форматирую длинные списки столбцов как одну строку сценария на столбец, затем имя столбца «AS» на следующей строке, если это необходимо, и пустую строку после четырех столбцов, чтобы было легче сохранить место в списке. Это также поддерживает выделение множества строк и выполнение Ctrl + K Ctrl + C, чтобы изменить их на комментарии, чтобы вы могли атаковать операцию вставки таким образом, но пропущенные столбцы должны были бы иметь значение NULL.
Роберт Карнеги

Ответы:

3

Если вы используете SQL Server 2016 (SP2, CU6 или новее), одним из вариантов является включение флага трассировки 460, например (QUERYTRACEON 460). Вывод будет указывать столбец и ошибочные данные.

Смотрите эту статью для деталей. https://www.brentozar.com/archive/2019/03/how-to-fix-the-error-string-or-binary-data-would-be-truncated/

Если вас не волнует усечение, вы можете SET ANSI_WARNINGS OFFигнорировать этот тип усечения.

user14472
источник
9

К сожалению, вы столкнулись с довольно старой «фичей». С 2008 года был открыт билет Connect, и в течение почти десяти лет это не было достаточно значительным, чтобы гарантировать исправление.

Как вы и предполагали, стандартный обходной путь - это select into...сравнение метаданных таблицы. Другая возможность - бинарный поиск в ошибочном столбце, но это тоже ручная работа. Есть несколько хаков для сравнения метаданных, но простого, элегантного решения не существует. Может быть, некоторые сторонние инструменты будут полезны, но я не знаю об этом.

vonPryz
источник
1

Использование (QUERYTRACEON 460) не сработало, когда я поставил его в конце моего запроса.

Я включил его на уровне БД, и это сработало:

DBCC TRACEON(460, -1);
GO

Но не забудьте оставить его включенным после того, как вы нашли и устранили проблему.

DBCC TRACEOFF(460, -1);
GO
Тейлор браун
источник