Як визначити стовпець (и), відповідальний за "Строкові або двійкові дані будуть усічені".


31

Я автоматично генерую деякі запити з кодом, який я написав на SELECT, з віддаленої бази даних Pg, і вставляю у локальну базу даних SQL Server. Однак одна з них генерує цю помилку:

[Microsoft] [Драйвер SQL Server ODBC] [SQL Server] Строкові або двійкові дані будуть усічені. (SQL-22001) [стан було 22001 зараз 01000]

[Microsoft] [ODBC Driver SQL Server] [SQL Server] Заява припинено. (SQL-01000) за адресою. \ Insert.pl 106.

Як я можу дізнатись, який стовпець генерує цю помилку та не вистачає довжини для введення? Чи є спосіб зробити це без грубої відгадки всіх varchar?

Відповіді:


35

Ні, він ніде не реєструється. Проголосуйте та заявіть про свою справу; це один із довгого списку речей, які слід виправити в SQL Server.

Це було запитано років тому на Connect (можливо, спочатку в часовій рамці SQL Server 2000 або 2005), а потім знову в новій системі зворотного зв'язку:

А тепер він був доставлений у SQL Server 2019 , SQL Server 2017 CU12 та з’явиться у майбутньому МС SQL Server 2016 SP2.

У першому загальнодоступному CTP SQL Server 2019 він відображається лише під прапором 460. Це звучить як секрет, але він був опублікований у цій газеті Microsoft . Це буде поведінка за замовчуванням (прапор сліду не потрібно) буде рухатися вперед, хоча ви зможете контролювати це за допомогою нової конфігурації бази даних VERBOSE_TRUNCATION_WARNINGS.

Ось приклад:

USE tempdb;
GO
CREATE TABLE dbo.x(a char(1));

INSERT dbo.x(a) VALUES('foo');
GO

Результат у всіх підтримуваних версіях до SQL Server 2019:

Msg 8152, рівень 16, стан 30, рядок 5
Рядок або двійкові дані будуть усічені.
Заява скасована.

Тепер на CTP SQL Server 2019 з увімкненим прапором сліду:

DBCC TRACEON(460);
GO

INSERT dbo.x(a) VALUES('foo');
GO
DROP TABLE dbo.x;
DBCC TRACEOFF(460);

Результат показує таблицю, стовпець та значення ( усічений , не повний ):

Msg 2628, рівень 16, стан 1, рядок 11
Рядок або двійкові дані будуть врізані в таблицю 'tempdb.dbo.x', стовпчик 'a'. Усечене значення: 'f'.
Заява скасована.

Поки ви не зможете кинути все та оновити до SQL Server 2019 або перейти на базу даних Azure SQL, ви можете змінити свій "автоматичний" код, щоб фактично витягнути max_length sys.columns, а також ім'я, яке ви все одно маєте отримати, а потім застосувати LEFT(column, max_length)або будь-який еквівалент PG Або, оскільки це означає, що ви мовчки втрачаєте дані, перевірте, які стовпці невідповідні, і виправте стовпці призначення, щоб вони вмістили всі дані з джерела. З огляду на доступ до метаданих до обох систем, а також на те, що ви вже пишете запит, який автоматично повинен відповідати стовпцям джерела -> пункту призначення (інакше ця помилка навряд чи буде вашою найбільшою проблемою), вам не доведеться робити жодної грубої сили здогадки взагалі.


2

Якщо у вас є доступ до запуску майстра імпорту та експорту SQL Server із студії управління SQL Server (база даних правою кнопкою миші> Завдання> Імпорт даних ...), створіть завдання, яке імпортує з клієнта SQL, використовуючи ваш запит як джерело даних до місця призначення стіл.

Перш ніж запустити імпорт, ви можете переглянути картографічне відображення даних, і воно покаже вам, які стовпці мають непослідовні типи полів. І якщо ви запустите завдання імпорту, воно покаже вам, який стовпець (и) не вдалося імпортувати.

Попередження про перевірку зразка:

Попередження 0x802092a7: Завдання потоку даних 1: Укорочення може статися через вставку даних із стовпця потоку даних "НАРАТИВНІ" довжиною 316 до стовпця бази даних "НАРАТИВНІ" довжиною 60. (Майстер імпорту та експорту SQL Server)


1

Зрештою, я не зміг знайти спосіб отримати інформацію про стовпчик, не записуючи її сам.

Це повідомлення про помилку було створено компанією DBD::ODBC, яку ви також можете використовувати sys.columns (max_length)(я просто не знаю як).

Я використовував такий код у своєму списку стовпців, щоб отримати список масивів з двома елементами COLUMN_NAME, та MAX_LENGTH(задокументовано в DBIcolumn_info() ).

my @max_lengths = map [ @{$_->fetchall_arrayref->[0]}[3,6] ]
    , map $dbh_mssql->column_info('database', 'dbo', $dest_table, $_)
    , @col_mssql
;

Тоді я виловив винятки INSERTі надрукував щось корисне. У цьому прикладі @$rowнаведені дані, надісланіsth->execute()

if ($@) {
        warn "$@\n";
        for ( my $idx=0; $idx <= $#{ $row }; $idx++ ) {
                Dumper {
                        maxlength => $max_lengths[$idx]->[1]
                        , name    => $max_lengths[$idx]->[0]
                        , length  => length( $row->[$idx] )
                        , content => $row->[$idx]
                };
        }
        die;
}

Крім того, будь ласка, проголосуйте та підтвердіть іншу відповідь


2
Я не ставив жодного посилання на код, sys.columnsтому що я абсолютно не мав уявлення, який код ви зараз використовуєте для "автоматичного" генерування ваших запитів. Дійсно, не так вже й складно, я б міг здогадатися про включення у свій код, ніж SELECT name, object_id, max_length FROM sys.columns;. Оскільки у вас вже є автоматичний код, який повинен робити це - або щось дуже подобається - я не вважав, що приклад необхідний.
Аарон Бертран

Я не впевнений, як sys.columnsпрацює з двома стовпцями, які мають однакові name. Крім того, я працював над використанням бібліотеки, а не sys, чому я б це зробив як обрану відповідь? Microsoft SQL doesn't have x, do y insteadє вагомим внеском, але якщо ваш yпоступається моєму y, я зроблю щось інше і відзначу його вибраним.
Еван Керролл

1
По суті, ваше питання полягав у тому, як я можу дізнатись, який стовпець генерував помилку (імовірно, щоб ви могли виправити це місце, замість того, щоб переробляти рішення). Я сказав вам, де шукати: sys.column. Це саме те, де слід шукати, щоб порівняти довжину стовпця джерела з довжиною стовпця пункту призначення. Як ви це зробите, залежить від вас. Я не сказав вам, як виправити свій код, тому що я абсолютно не маю уявлення про те, як створювався ваш автоматичний запит, так що, як я вже говорив, не мав уявлення, як додати визначення довжини до будь-якого запиту, який ви вже мали .
Аарон Бертран

1

Нарешті, Microsoft вирішила надати змістовну інформацію для String or binary would be truncatedзапуску з SQL Server 2016 SP2 CU, SQL Server 2017 CU12 та SQL Server 2019.

Інформація тепер включає в себе як стовпчик таблиці правопорушень (повністю кваліфіковане ім'я), так і значення, яке порушує (усічене на 120 символів):

Msg 2628, рівень 16, стан 1, рядок x Рядок або двійкові дані будуть врізані в таблицю "TheDb.TheSchema.TheTable", стовпець "Колонка". Усечене значення: '...'. Заява скасована.

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