SQL Server Insert Into - Як визначити стовпець, що викликає помилку усікання


11

У мене зберігається процедура, яка вставляє 650 полів у таблицю. Вставка не вдається з помилкою усікання.

Це просто

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

Нижче наводиться повідомлення про помилку:

Повідомлення 8152, рівень 16, стан 14, процедура DSP_Procedure, рядок 1075 Рядок або двійкові дані будуть усічені.

Чи є швидкий спосіб я визначити, яке поле викликає помилку усічення?

Той факт, що оператор select, який потрібно вставити в таблицю, містить 650 полів, ускладнює точне визначення того, яке поле викликає помилку усікання.

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

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

Я використовую SQL Server 2014.

Будь-які простіші альтернативи?


1
Я б зайшов до INFORMATION_SCHEMA.COLUMNS і порівняв типи даних з тими, які ви намагаєтеся вставити. На жаль, SQL-сервер не має динамічних типів даних для оголошення змінної, як це робить ORACLE.
MguerraTorres

2
Я б застосував ваш другий варіант, вставте в нову (або #temp) таблицю, а потім порівняйте довжини стовпців. Або ви можете обернути LEN () навколо всіх стовпців у виділеному, а потім мати зовнішній запит зробити MAX () для кожного ..., що дасть вам найбільшу довжину тексту для полів. Звичайно, це передбачає, що це те, що викликає проблеми. Не використовуєте smalldatetime або tinyint?
Джонатан Фійт

1
Я б пішов із підходом "Select Into" і порівняв довжину стовпців, так. Можливо, з "WHERE 1 = 0", щоб таблиця не мала рядків. Незручно, якщо ваш SELECT не містить унікальних імен для вибраних стовпців. Я форматую довгі списки стовпців як один рядок сценарію на стовпець, потім "AS" назва стовпця в наступному рядку, якщо потрібно, і порожній рядок після чотирьох стовпців, щоб полегшити утримання в списку. Це також підтримує вибір багатьох рядків та виконання Ctrl + K Ctrl + C, щоб змінити їх на коментарі, щоб ви могли таким чином атакувати операцію "Вставити", але стовпці, що залишилися, повинні бути зведені нанівець.
Роберт Карнегі

Відповіді:


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ігнорувати цей тип усічення.


9

На жаль, ви зіткнулися з досить старої "особливістю". Квиток на Connect було відкрито з 2008 року, і майже десять років це не було достатньо вагомим для того, щоб вимагати виправлення.

Стандартний обхідний шлях є, як ви зрозуміли, з select into...подальшим порівнянням метаданих таблиці. Іншою можливістю є двійковий пошук стовпця-порушника, але це теж ручна робота. Існує кілька хак для порівняння метаданих, але простого, елегантного рішення не існує. Можливо, якісь сторонні інструменти допоможуть, але я не знаю такого.


1

Використання (QUERYTRACEON 460) не працювало для мене, коли ставити його в кінці мого запиту.

Я ввімкнув його на рівні БД, і він спрацював:

DBCC TRACEON(460, -1);
GO

Але не забудьте вимкнути її, як тільки ви знайшли та виправили проблему, не залишайте її!

DBCC TRACEOFF(460, -1);
GO
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.