「文字列またはバイナリデータが切り捨てられる」原因となっている列を特定するにはどうすればよいですか。


31

リモートPgデータベースからSELECTに書き込んだコードを使用していくつかのクエリを自動的に生成し、ローカルSQL Serverデータベースに挿入しています。ただし、そのうちの1つがこのエラーを生成しています。

[Microsoft] [ODBC SQL Server Driver] [SQL Server]文字列またはバイナリデータは切り捨てられます。(SQL-22001)[状態は22001でしたが、現在は01000]

[Microsoft] [ODBC SQL Server Driver] [SQL Server]ステートメントは終了しました。(SQL-01000)。\ insert.pl行106。

どの列がそのエラーを生成しており、入力の長さが不足しているかを調べるにはどうすればよいですか 総当たり攻撃をせずにこれを行う方法はありvarcharますか?

回答:


35

いいえ、どこにも記録されません。投票に行き、ビジネスケースを述べてください。これは、SQL Serverで修正する必要のある長いリストの1つです。

これは何年も前にConnectで(おそらく最初にSQL Server 2000または2005の時間枠で)要求され、次に新しいフィードバックシステムで要求されました。

そして現在、SQL Server 2019、SQL Server 2017 CU12で提供されており、将来のSQL Server 2016 SP2 CUに登場します。

SQL Server 2019の最初の公開CTPでは、トレースフラグ460の下でのみ表示されます。これはちょっとした秘密に聞こえますが、このマイクロソフトホワイトペーパーで公開されました。これは今後のデフォルトの動作(トレースフラグは不要)になりますが、新しいデータベーススコープの構成を介してこれを制御できますVERBOSE_TRUNCATION_WARNINGS

以下に例を示します。

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

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

SQL Server 2019より前のすべてのサポートされているバージョンの結果:

メッセージ8152、レベル16、状態30、行5
文字列またはバイナリデータは切り捨てられます。
ステートメントは終了されました。

次に、トレースフラグを有効にしたSQL Server 2019 CTPで:

DBCC TRACEON(460);
GO

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

結果には、テーブル、列、および(切り捨てられ完全ではない)値が表示されます。

メッセージ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 Management StudioからSQL Serverインポートおよびエクスポートウィザードを実行するアクセス権がある場合(データベースを右クリックし、[タスク]> [データのインポート...])、クエリをデータソースとしてSQLクライアントからインポートするタスクを作成します。表。

インポートを実行する前に、データマッピングを確認すると、どの列に一貫性のないフィールドタイプがあるかがわかります。また、インポートタスクを実行すると、インポートに失敗した列がわかります。

サンプル検証警告:

警告0x802092a7:データフロータスク1:長さ316のデータフロー列 "NARRATIVE"から長さ60のデータベース列 "NARRATIVE"にデータを挿入するため、切り捨てが発生する場合があります。(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同じを持つ2つの列がどのように動作するかわかりませんname。また、私はライブラリではなく、ライブラリを使用して動作するものを得ましたがsys、なぜそれを選択された答えとしてしますか?Microsoft SQL doesn't have x, do y insteadは有効な貢献ですが、あなたyが私のyに劣っている場合、私は何か違うことをして、それを選択済みとしてマークします。
エヴァンキャロル

1
あなたの質問は、本質的に、どの列がエラーを生成していたかをどのように見つけるのかでした(おそらく、ソリューションを再設計する代わりに、その1つの場所を修正できます)sys.columnsを参照してください。これは、ソース列の長さと宛先列の長さを比較するために正確に見るべき場所です。それをどうするかはあなた次第です。コードを修正する方法を教えませんでした。なぜなら、最初に自動マジッククエリがどのように生成されたかまったくわからないため、既に述べたように、すでにあるクエリに長さの決定を追加する方法がわからなかったからです。
アーロンバートランド

1

最後に、MicrosoftはString or binary would be truncated、SQL Server 2016 SP2 CU、SQL Server 2017 CU12、およびSQL Server 2019 で開始するための有意義な情報を提供することを決定しました

情報には、問題のあるテーブル列(完全修飾名)と問題のある値(120文字で切り捨てられた)の両方が含まれるようになりました。

メッセージ2628、レベル16、状態1、行x文字列またはバイナリデータは、テーブル 'TheDb.TheSchema.TheTable'、列 'TheColumn'で切り捨てられます。切り捨てられた値: '...'。ステートメントは終了されました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.