0

我正在编写代码以每天将数十个中等大小的文本文件导入 SQL SERVER。目前,这些已导入 FOXPRO 数据库。我正在转换为使用 SQL SERVER。我已经完成了所有的固定长度文件,但是最后三个数据文件有一个可变长度字段作为每行的最后一个字段。最后一个字段的长度可达 32,000 字节。在数据库中,我已将其声明为 VARCHAR(MAX)。

字段终止符是行终止符,它是换行符。也就是说,该行以单个“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>

不幸的是,当我使用它时,它会导入一行然后终止。我怎样才能让这个东西读取整个文件?

样本数据:

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 回答