0

我正在使用 bcp 从远处的其他人从另一个表导出的 CSV 加载一个表,并且遇到了一些问题。我原来的两个问题:一个导出的字段是一个需要以 varchar 字段结尾的 int,另一个字段需要用静态字符串填充。好吧,第一个没什么大不了的,Chad 的回答让我想到了@{n='Col3';e={'ABC'}}语法。但是我在正确加载数据时遇到了几个问题。

  1. 有时一个值可能没有空格,有时它可能。如何在 bcp 格式文件中指定分隔符?我问是因为大概我需要用引号括起来。

    一种。我应该用引号将中间 CSV 文件中的值包装起来吗?

  2. 在我的测试代码中,它将列标题和换行推入 Col1,第一行的实际值为 Col1。

  3. 在我实际的、未经处理的代码中,我进入String data, right truncation了第一行,尽管第二行插入正常。

无论如何,我从其他地方获得的初始 CSV 数据看起来像这样(注意:没有标题行)

"ABC123",123456,"APPLE"
"XYZ789",456789,"ORANGE"

目标SQL表是这样的

Col1 varchar(50) (Primary Key)
Col2 varchar(50)
Col3 varchar(50)
Col4 varchar(50)

我需要将ABC123加载到123456Col1,将Export1加载到APPLE中。Export1是静态字符串。我在 Powershell 1.0 中这样做。Col2Col3Col4

编辑:乍得的 import-csv | export-csv 看起来很有希望,但它不喜欢缺少标题,并且 PS 1.0 不支持 -Header 选项。

编辑:上面的编辑描述以反映我是如何走到这一点的。四列表格和三列 CSV 显然是简化的。一个真正的列是一个城市,因此它可以包含简单的字符串或需要引用的字符串。此时我的 Powershell 1.0 代码如下。

$SQLSERVER="svr"
$SQLTABLE="test"
$SQLUSER="u"
$SQLPASS="p"

$TESTFILE = "testdata.csv"
$TESTFILEHDR = "testdata-wHeaders.csv"
$TESTFILEFIX = "testdata-fixed.csv"
$OrigHeaders = "`"Col1`",`"Col2`",`"Col3`"`n"

function Create-BcpFormat($fileName)
{
@"
<?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='CharTerm' TERMINATOR=',"' COLLATION='SQL_AltDiction_CP850_CI_AS'/>
  <FIELD ID='2' xsi:type='CharTerm' TERMINATOR='",' COLLATION='SQL_AltDiction_CP850_CI_AS'/>
  <FIELD ID='3' xsi:type='CharTerm' TERMINATOR=',' COLLATION='SQL_AltDiction_CP850_CI_AS'/>
  <FIELD ID='4' xsi:type='CharTerm' TERMINATOR='\r\n' COLLATION='SQL_AltDiction_CP850_CI_AS'/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="1" NAME="Col1" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="2" NAME="Col2" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="3" NAME="Col3" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="4" NAME="Col4" xsi:type="SQLVARYCHAR"/>
 </ROW>
</BCPFORMAT>
"@ | Set-Content $filename
}

## GHI456 is already in the table, clean out previous attempts
"`nclean test table:"
osql @("-S","$SQLSERVER","-U","$SQLUSER","-P","$SQLPASS","-Q",
    """delete from $SQLTABLE where col1 <> 'GHI456' or col1 is null""")

## Prepend
$body = [string]::join([environment]::NewLine, (gc $TESTFILE))
$OrigHeaders + $body > $TESTFILEHDR

"`nTESTFILEHDR:"
type $TESTFILEHDR

$accts = Import-csv $TESTFILEHDR | select 'Col1', 'Col2', @{n='Col3';e={'ABC'}}, @{n='Col4';e={$_.Col3}}
$accts
$accts | Export-Csv $TESTFILEFIX -NoTypeInfo

"`nTESTFILEFIX:"
type $TESTFILEFIX

$BCPFMTFILE = "bcp.fmt"
$BCPERRFILE = "bcp.err"
Create-BcpFormat $BCPFMTFILE
bcp @("$SQLTABLE","in","$TESTFILEFIX","-S","$SQLSERVER","-U","$SQLUSER","-P","$SQLPASS","-f",$BCPFMTFILE,"-e",$BCPERRFILE)
Remove-Item $BCPFMTFILE

"`ntest table:"
osql @("-S","$SQLSERVER","-U","$SQLUSER","-P","$SQLPASS","-Q",
    """select left(Col1,20) 'Col1', left(Col2,8) 'Col2', left(Col3,8) 'Col3', left(Col4,8) 'Col4' from $SQLTABLE""")

"`nBCPERRFILE:"
type $BCPERRFILE
4

2 回答 2

2

为什么不在 PowerShell 中以编程方式使用 ADO.NET 的 SqlBulkCopy?您将拥有完全控制权:逐行读取、转换数据并根据需要填充 DataTable 并批量调用 WriteToServer。请参阅http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

于 2010-08-24T06:05:16.557 回答
1

你可以做这样的事情来添加列

导入-csv .\forum.csv -Header "Col1","Col2","Col4" | 选择 Col1, Col2, @{n='Col3';e={'Export1'}}, Col4 | 导出-Csv ./forum2.csv -NoTypeInfo

于 2010-08-19T22:22:06.530 回答