2

SQLSERVER テーブルに毎日インポートしたいフラット (テキスト) ファイルがたくさんあります。今のところ、手順を実行している間、1 つのファイルをインポートしたいだけです。もちろん、これを行うために c# コードを書くことはできますが、これは正しい方法ではないと感じており、xml 形式のファイルで一括挿入のようなものを使用したいと考えています。

最初のサンプル ファイルは次のようになります (sample.dat):

Q     RR201110010000000002000000000000232000
N     X4201110010000000001500000000000160000

注: このファイルの 16 進ダンプは、各行が正確に改行文字で終了していることを示しています。

私のxml翻訳ファイルは次のようになります。

<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <RECORD>
  <FIELD ID="1" xsi:type="CharFixed" LENGTH="6"/>
  <FIELD ID="2" xsi:type="CharFixed" LENGTH="2"/>
  <FIELD ID="3" xsi:type="CharFixed" LENGTH="8"/>
  <FIELD ID="4" xsi:type="CharFixed" LENGTH="14"/>
  <FIELD ID="5" xsi:type="CharFixed" LENGTH="14"/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="1" NAME="c1" xsi:type="SQLNCHAR"/>
  <COLUMN SOURCE="2" NAME="c2" xsi:type="SQLNCHAR"/>
  <COLUMN SOURCE="3" NAME="c3" xsi:type="SQLCHAR"/>
  <COLUMN SOURCE="4" NAME="c4" xsi:type="SQLINT" />
  <COLUMN SOURCE="5" NAME="c5" xsi:type="SQLINT" />
 </ROW>
</BCPFORMAT>

私のクエリは次のようになります。

SET LANGUAGE us_english;
GO
SET DATEFORMAT ymd;
go
BULK INSERT 
  PROJ.dbo.Costs
  FROM 'C:\somewhere\test01\SAMPLE.DAT'
  WITH
  (
  DATAFILETYPE ='CHAR',
  FORMATFILE='C:\somewhere\test01\TRANSLATE02.XML',
  ERRORFILE='C:\somewhere\test01\ERRORS.TXT',
  ROWTERMINATOR='\n'
  )
  GO

このスクリプトを実行すると、行 2 からオーバーフロー エラーが発生します (つまり、SQL テーブルには表示されませんが、行 1 は正しく変換されたように見えます)。エラー行 (行 2) は改行で始まります! もちろん、それでは 4 番目のフィールドがオーバーフローします。そのため、スクリプトは ROWTERMINATOR を理解していないようです。\r が表示されない場合に備えて、'\n'、'\r'、'\r\n'、'\n\r' を試しました。役立たず。

また、ROWTERMINATOR を使用した一括挿入 txt エラーに従って、わずかに異なる SQL コマンドを試みました 。

同じエラーが発生しました。

私が見逃しているものについて何か考えはありますか?

リクエストに応じて、sample.dat のマンジされた 16 進ダンプを次に示します。

000000: 41 20 20 20  20 20 XX XX  32 30 31 31  31 30 30 31  Q     RR20111001
000010: 30 30 30 30  30 30 30 30  30 31 35 30  30 30 30 30  0000000001500000
000020: 30 30 30 30  30 30 31 35  30 30 30 30  0A ZZ 20 20  000000150000.N
000030: 20 20 20 XX  XX 32 30 31  31 31 30 30  31 30 30 30     X420111001000
000040: 30 30 30 30  30 30 32 30  30 30 30 30  30 30 30 30  0000002000000000
000050: 30 30 30 32  33 32 30 30  30 0A ZZ 20  20 20 20 20  000232000.Y

XX と ZZ はマスクされている (実際のデータではない) ことに注意してください。これがあまり混乱しないことを願っています。

以下の私の解決策は機能しますが、この問題もここで議論されており、解決策は私にとってより良いようです(確認していませんが、次のファイルで試してみると思います)。 一括挿入行ターミネータの問題

4

4 に答える 4

1

答え(まあ、少なくとも1つの答え)は恥ずかしいほど単純です。

XMLのFIELDSのリストに偽の1文字のフィールドを追加しました。

<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <RECORD>
  <FIELD ID="1" xsi:type="CharFixed" LENGTH="6"/>
  <FIELD ID="2" xsi:type="CharFixed" LENGTH="2"/>
  <FIELD ID="3" xsi:type="CharFixed" LENGTH="8"/>
  <FIELD ID="4" xsi:type="CharFixed" LENGTH="14"/>
  <FIELD ID="5" xsi:type="CharFixed" LENGTH="14"/>
  <FIELD ID="6" xsi:type="CharFixed" LENGTH="1"/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="1" NAME="c1" xsi:type="SQLNCHAR"/>
  <COLUMN SOURCE="2" NAME="c2" xsi:type="SQLNCHAR"/>
  <COLUMN SOURCE="3" NAME="c3" xsi:type="SQLCHAR"/>
  <COLUMN SOURCE="4" NAME="c4" xsi:type="SQLINT" />
  <COLUMN SOURCE="5" NAME="c5" xsi:type="SQLINT" />
 </ROW>
</BCPFORMAT>

その最後のフィールドを(対応するCOLUMNタグを使用して)書き込んでいないことに注意してください。これにより、EOL(/ n)がダミーフィールドに読み込まれます。これがBULKINSERTコマンドのROWTERMINATORの動作のバグでない場合は、少なくとも非常に直感的ではありません。つまり、ROWTERMINATORはNOOPのように見えます。

観察1:列3はYYYYMMDD形式の日付ですが、対応するSOURCE3は実際にはSMALLDATETIMEです。自動的に正しく変換されます。

観察2:ソース3および4はdecimal(14、2)として定義されます。対応するフィールドの最後の2文字を100分の1として使用するように、入力をスケーリングすると思いました。私はどちらかをすることができます。自動的にスケーリングする方法を見つける(推奨)またはb。後処理を行って100で割ります(これは別の質問です。私には興味深いと思われるので、ここで注意してください)。

いずれにせよ、これは問題の1つの解決策のようです。回答ありがとうございます。

補遺(余談ですが):sqlコマンドの最後にUPDATE SETコマンドを使用してmoneyフィールドを100で除算し、オプションb(観察2で説明)を使用することにしました。

最終的な製品は、「sqlcmd」を何度も呼び出すバッチファイルになります。その後、最後尾でperlスクリプトを実行して、さまざまなエラーファイルのエントリを確認します。

もう1つ、BULK INSERTコマンドにリストされているエラーファイルは、これを実行するときに存在しない必要があることに注意してください。そうしないと、それ自体が別のエラーを生成します。前処理中にそれを処理します。

とにかく、ありがとう。

于 2012-05-23T16:12:17.650 に答える
1

ファイルからデータベースにデータを変換するには、SSIS "SQL Server Integration Services" を使用する必要があります。そして、この変換を SQL Server で実行して、毎日自動的に変換することができます。

于 2012-05-23T05:48:42.160 に答える
1

固定形式のテキストの XML スキーマ ファイルに関する SQL Server の記事では、RECORD 要素でターミネータが指定されています。

<RECORD>
  <FIELD ID="1" xsi:type="CharFixed" LENGTH="10"/>
  <FIELD ID="2" xsi:type="CharFixed" LENGTH="6"/>
  <FIELD ID="3" xsi:type="CharTerm" TERMINATOR="\r\n"
</RECORD>

(上記のタイプミスに注意してください。)おそらくこれが、クエリでの指定が無視される理由です。

于 2015-10-13T10:25:29.630 に答える
0

試してみてくださいchar(13)、それはSQLキャリッジリターンです。またchar(13) + char(10)、キャリッジリターン/ラインフィード。

于 2012-05-22T19:57:21.743 に答える