Почему «Строковые или двоичные данные будут усечены» более описательной ошибкой? - PullRequest
25 голосов
/ 30 марта 2010

Для начала: я понимаю, что означает эта ошибка - я не пытаюсь разрешить ее экземпляр.

Общеизвестно, что эту ошибку трудно устранить, потому что, если вы получаете ее, вставляя миллион строк в таблицу шириной 100 столбцов, практически невозможно определить, какой столбец какой строки вызывает ошибку - вы должны изменить свой процесс на вставьте по одной строке за раз, а затем посмотрите, какая из них не удалась. Это, мягко говоря, боль.

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

String or Binary data would be truncated
Error inserting value "Some 18 char value" into SomeTable.SomeColumn VARCHAR(10)

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

Ответы [ 7 ]

15 голосов
/ 31 марта 2010

Оказывается, для MS Connect существует открытый "запрос на добавление функций" - я бы рекомендовал вам проголосовать за него, если вы хотите, чтобы функциональность изменилась.

https://connect.microsoft.com/SQLServer/feedback/details/339410/

ДОБАВЛЕНО:

Похоже, что есть еще одна просьба об этой же функции (хотя и с плохим названием), которая была выдающейся со времени разработки Юкона в 2005 году, и за которую я бы посоветовал людям проголосовать:

https://connect.microsoft.com/SQLServer/feedback/details/125347/

Обновление 2016

Кажется, Microsoft пыталась удалить доказательства истинного возраста этой ошибки. Справедливо. Найдите старый сайт, заархивированный здесь.

6 голосов
/ 13 ноября 2012

Не найдя приемлемого ответа, я пришел к следующему:

  1. Получить запрос, который вызывает проблемы (вы также можете использовать SQL Profiler, если у вас нет источника)
  2. Удалите все предложения WHERE и другие неважные части, пока в основном не останетесь только части SELECT и FROM
  3. Добавить WHERE 0 = 1 (при этом будет выбрана только структура таблицы)
  4. Добавить INTO [MyTempTable] непосредственно перед предложением FROM

У вас должно получиться что-то вроде

SELECT
 Col1, Col2, ..., [ColN]
INTO [MyTempTable]
FROM
  [Tables etc.]
WHERE 0 = 1

Это создаст таблицу с именем MyTempTable в вашей БД, которую вы сможете сравнить со структурой вашей целевой таблицы, чтобы увидеть, чем они отличаются, то есть вы можете сравнить столбцы в обеих таблицах.

РЕДАКТИРОВАТЬ: вы можете сравнить типы данных и размеры столбцов каждого столбца в исходной таблице и MyTempTable, чтобы увидеть, чем они отличаются. Все имена столбцов в вашей новой таблице будут такими же, как в старой, а также типы данных и размеры будет таким же, ЗА ИСКЛЮЧЕНИЕМ, где находится столбец-нарушитель. Другими словами, с помощью этого запроса SQL автоматически создаст столбцы, достаточно большие для обработки максимально возможной записи из исходной таблицы

4 голосов
/ 04 апреля 2011

Ответ на DUP, который был закрыт, поэтому отвечайте здесь вместо этого. Этот шаблон можно использовать, если он несколько сложен, но он может быть полезен, когда нетрудно изменить приложение или настроить профилировщик, чтобы увидеть, что происходит. Иногда вам просто нужно, чтобы ошибка распространялась на само приложение, чтобы вы могли видеть прямо из приложения правильное и полезное сообщение об ошибке.

В этих случаях быстрое проникновение в БД с помощью этого решения сэкономит вам много времени. Сохраните его как шаблон и внесите в него быстрые изменения, чтобы решить эту проблему на любом столе.

Проблема

Пример таблицы

create table StringTruncation
(A int, B varchar(10), C nvarchar(5), D nvarchar(max), E datetime)

Пример выписки

insert StringTruncation values
(1, '0123456789', 'abcdef', 'This overflows on C', GETDATE())

страшная бесполезная ошибка

Msg 8152, Level 16, State 4, Line 1
String or binary data would be truncated.
The statement has been terminated.

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

Решение

-- First move the table out of the way
exec sp_rename StringTruncation, StringTruncation_;

-- cover it with a query
create view dbo.StringTruncation
with schemabinding
as
select
    A,
    convert(Nvarchar(max),B) B,
    convert(Nvarchar(max),C) C,
    D, E
from dbo.StringTruncation_
GO

-- use a trigger to allow INSERTs, with the length checks thrown in
create trigger dbo.trig_ioi_StringTruncation
on StringTruncation
instead of insert
as
set nocount on
declare @offending nvarchar(max)
select TOP 1 @offending = case
    when len(C) > 5 then 'Data too long for Column [C] Size 5: ' + C
    when len(B) > 10 then 'Data too long for Column [D] Size 10: ' + B
    end
from inserted
where len(C) > 5 or len(B) > 10
GO

-- keep good data
if @@rowcount = 0
    insert StringTruncation_
    select * from inserted
else
    raiserror(@offending,16,1)
GO

Проверьте это

insert StringTruncation values
(1, '0s123456789', 'abcde', 'This overflows on C', GETDATE())

Результат

Сообщение 50000, уровень 16, состояние 1, процедура trig_ioi_StringTruncation, строка 18
Данные слишком длинные для столбца [D]. Размер 10: 0s123456789

(Затронут 1 ряд)

Примечания

  • Требуется зеркальный триггер для ОБНОВЛЕНИЙ
  • В настоящее время он будет сообщать только о первом поврежденном столбце записи. Можно сообщить более одного столбца записи, но я считаю, что это на самом деле контрпродуктивно.
0 голосов
/ 05 сентября 2013

У меня тоже была эта ошибка, но я нашел причину:

<option>description</option>  <-- this is not error but is wrong
<option value="option1">option1</option>
<option value="option2">option2</option>
<option value="option3">option3</option> 

Мое приложение MVC получает "значение" как пустой стринг муравей, который вызывает исключение

0 голосов
/ 31 марта 2010

Описательные сообщения об ошибках в программных системах так же хороши, как и несуществующие.

Это справедливо не только для СУБД, но и для любого программного обеспечения, которое только можно себе представить.

Я думаю, что основная причина в том, что "хорошие описательные сообщения об ошибках" занимают слишком много времени для реализации. Не является ли частью культуры обычного разработчика программного обеспечения тратить много времени на размышления о том, «какую информацию хотел бы видеть пользователь, если произойдет это конкретное исключение»? Программисты, которые должны записать код для предоставления «хороших описательных сообщений об ошибках», видят только стоимость (свое время), а не выгоду.

Одно из самых последних сообщений об ошибках, которые я получил от системы программного обеспечения: «Что-то не так произошло. Пожалуйста, повторите попытку позже». Без шуток.

0 голосов
/ 31 марта 2010

Краткий ответ: Вот только как это.

Более длинный ответ: Я мог видеть значение в показе номера строки и столбца, возможно, но, вероятно, не имеет смысла показывать фактическую усеченную информацию. С сценарием VARCHAR (10) это, вероятно, не имеет большого значения, но чрезмерно большой размер данных будет очень полезным. Но, надеюсь, никто здесь не вставляет ничего, что может удержать VARCHAR (MAX);)

0 голосов
/ 30 марта 2010

Microsoft ленится?

Кстати, вам не нужно пробовать каждую строку вставлять отдельно. Просто запросите max (len (field)) для каждого текстового столбца, начиная с подозреваемых, которые могут быть причиной.

...