0

私は毎日、数十の中程度のサイズのテキスト ファイルを SQL SERVER にインポートするコードを書いています。現在、これらは FOXPRO データベースにインポートされています。SQL SERVER を使用するように変換しています。すべての固定長ファイルを完成させましたが、最後の 3 つのデータ ファイルには、各行の最後のフィールドとして可変長フィールドがあります。この最終フィールドの長さは最大 32,000 バイトです。データベースでは、これを VARCHAR(MAX) として宣言しました。

フィールド ターミネータは、改行である行ターミネータです。つまり、行は、2 つの改行ではなく、フィールドの終わりと行の終わりの両方を示す単一の「0x0a」で終了します。

私が使用しているSQLは次のとおりです。

BULK INSERT 
  [MyDB].[dbo].[X]
  FROM 'C:\temp\eep.dat'
  WITH
  (
  DATAFILETYPE ='CHAR',
  FORMATFILE='C:\temp\translate_eep.xml',
  ERRORFILE='C:\temp\ERR_eep.TXT',
  FIELDTERMINATOR='0X0A',
  ROWTERMINATOR='0X0A'
  )
GO

Translate_eep.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="5"/>
  <FIELD ID="2"   xsi:type="CharFixed" LENGTH="5"/>
  <FIELD ID="3"   xsi:type="CharFixed" LENGTH="5"/>
  <FIELD ID="4"   xsi:type="CharTerm"  TERMINATOR="0X0A"/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="1"  NAME="c1"  xsi:type="SQLCHAR"/>
  <COLUMN SOURCE="2"  NAME="c2"  xsi:type="SQLCHAR"/>
  <COLUMN SOURCE="3"  NAME="c3"  xsi:type="SQLCHAR"/>
  <COLUMN SOURCE="4"  NAME="c4"  xsi:type="SQLCHAR"/>
 </ROW>
</BCPFORMAT>

残念ながら、これを使用すると、1行インポートしてから終了します。ファイル全体を読み取るにはどうすればよいですか?

サンプルデータ:

ABCDE12345EMILYLove is not all. It is not meat, nor drink, nor slumber<lf>
FGHIJ67890SNL  Oh, no! Mr. bill!<lf>
KLMNO24680ALEX All Nature is but art, unknown to thee<lf>
PQRST13579FROSTSome say the world will end in fire,<lf>
4

1 に答える 1

0

BULK INSERT を使用してこの問題を解決できませんでした。可変長フィールドを持つ最後の 3 つのテーブルについては、Perl を使用してストアド プロシージャでデータをアップロードしました。次のようになります。

#!/usr/bin/perl

use strict;
use DBI;

# Open the database
my ($dbh,$sth);
my $db_name="MyDB";
my $db_instance="AMACHINE";

$dbh = DBI->connect("DBI:ODBC:Driver={SQL Server};Server=$db_instance;Database=$db_name;") or die "Unable to connect";



my $sql = "DELETE [MyDB].[dbo].[X]" ;
my $sth = $dbh->prepare($sql);
$sth->execute();

my $sql = "{call MyDB.dbo.Import_X_table(?, ?, ?, ?)}" ;
my $sth = $dbh->prepare($sql);

my $in_datafile = "eep.dat";
open INF, $in_datafile || die "Unable to open file $in_datafile\n";

my $lc = 0;  # line counter;
my $buffer;
while ( $buffer = <INF> )
{
  $lc++;
  my $reference = substr($buffer, 0, 5);
  my $code      = substr($buffer, 5, 5);
  my $name      = substr($buffer, 10, 5);
  my $narrative = substr($buffer, 15); #everything after character 14

  $sth->execute($reference, $code, $name, $narrative);

}

ストアド プロシージャは次のようになります。

USE [MyDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[Import_X_table]
    @ent       varchar(5),
    @cd        varchar(5),
    @nm        varchar(5),
    @narr      varchar(max)
AS
BEGIN
    SET NOCOUNT ON
    INSERT INTO [MyDB].[dbo].[X] VALUES (@ent,@cd,@nm, @narr)
END

私はこの解決策が好きではありませんが、私が思いつくことができる最も迅速な回避策です。差し迫った問題を解決するのではなく、それを軽率に回避することで目的を達成します。

これをこの問題の「解決策」として受け入れるべきかどうかはわかりません。

于 2012-07-03T17:04:28.410 に答える