【问题标题】:SQL Server BULK INSERT fixed length char dataSQL Server BULK INSERT 固定长度字符数据
【发布时间】:2012-04-01 23:07:13
【问题描述】:

我使用 SQL Server 2008 并且有一个包含 5 个字符类型列的表。

CREATE TABLE [dbo].[deviceDataBulk](
[f1] [char](9) NULL,
[f2] [char](5) NULL,
[f3] [char](7) NULL,
[f4] [char](7) NULL,
[f5] [char](6) NULL)

我还有一个bcp格式的文件;

<RECORD>
 <FIELD ID="1" xsi:type="CharFixed" LENGTH="9" COLLATION="Turkish_CI_AS"/>
 <FIELD ID="2" xsi:type="CharFixed" LENGTH="5" COLLATION="Turkish_CI_AS"/>
 <FIELD ID="3" xsi:type="CharFixed" LENGTH="7" COLLATION="Turkish_CI_AS"/>
 <FIELD ID="4" xsi:type="CharFixed" LENGTH="7" COLLATION="Turkish_CI_AS"/>
 <FIELD ID="5" xsi:type="CharFixed" LENGTH="6" COLLATION="Turkish_CI_AS"/>
</RECORD>
<ROW>
 <COLUMN SOURCE="1" NAME="f1" NULLABLE="YES" xsi:type="SQLCHAR"/>
 <COLUMN SOURCE="2" NAME="f2" NULLABLE="YES" xsi:type="SQLCHAR"/>
 <COLUMN SOURCE="3" NAME="f3" NULLABLE="YES" xsi:type="SQLCHAR"/>
 <COLUMN SOURCE="4" NAME="f4" NULLABLE="YES" xsi:type="SQLCHAR"/>
 <COLUMN SOURCE="5" NAME="f5" NULLABLE="YES" xsi:type="SQLCHAR"/>
</ROW>

我的数据文件包含固定长度的字符数据,每行没有字段终止符。因此,一整行的​​长度为 34 个字符。

我的问题是字段 4 和字段 5 可能不存在于每一行。我在该文件中可能有 21 个字符长行或 28 个字符长行。

不存在字段 5 存在而字段 4 不存在的情况。

文本文件的可能场景是 ;

f1 f2 f3 f4 f5
f1 f2 f3 f4
f1 f2 f3

我无法使用BULK INSERT 插入此文件。我希望BULK INSERT 在没有这些字段时插入空值,如果工具到达行尾,只需为其余字段插入空值。

【问题讨论】:

    标签: sql-server bulkinsert bcp


    【解决方案1】:

    两步法怎么样?首先将数据作为“大行”加载到临时表中,然后使用第二个查询将原始行拆分为相应的字段并相应地处理“缺少 f5 和/或 f4 列”的情况?

    看起来(或多或少)像这样:(未经测试!)

    CREATE TABLE [dbo].[deviceDataBulk_staging](
     [rowid] int IDENTITY(1 , 1) PRIMARY KEY,
     [raw] [varchar](34) NOT NULL)
    
    GO
    BULK INSERT [deviceDataBulk_staging]
    FROM '<your file>' 
    -- not sure if you really need a format-file here, 
    -- simply make sure to pass the correct line-separator if it is 'exotic'.
    
    GO
    
    INSERT [deviceDataBulk] (f1, f2, f3, f4, f5)
    SELECT f1 = SubString([raw], 1 , 9),
           f1 = SubString([raw], 10 , 5),
           f1 = SubString([raw], 15 , 7),
           f1 = (CASE WHEN Length([raw] < 22 THEN NULL ELSE SubString([raw], 22 , 7) END),
           f1 = (CASE WHEN Length([raw] < 29 THEN NULL ELSE SubString([raw], 29 , 6) END)
      FROM [deviceDataBulk_staging]
     ORDER BY [rowid]
    

    暂存文件将如下所示:

    [rowid] 用于保持与文件中最初的顺序相同的顺序,您可能不需要它,但恕我直言,开销很小,而且 MSSQL 对 HEAP 表并不太热衷,所以有它是“好东西[Tm]”

    【讨论】:

    • 如果这是唯一可用的解决方案,哪种方式更有效,使用 sql server 解析这些 char 值或编写 c# windows 应用程序并让它解析(从文件中逐行读取,进行解析和插入行)。我试图总结一下情况,实际上目标表有35列,最后6列可能是空的。数据文件有60行数据。我将每 5 分钟生成一个新数据文件。
    • 如果你只需要 60 行数据,我不会太担心性能。尽管 SQL 可能不擅长字符串操作(什么语言?),但恕我直言,它做得不错。写 35 列的语句并不好玩 =P
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 1970-01-01
    • 2015-05-02
    相关资源
    最近更新 更多