【问题标题】:BCP update database table base on output from powershellBCP 根据 powershell 的输出更新数据库表
【发布时间】:2019-10-22 04:03:42
【问题描述】:

我有 4 个文件,其 csv 标头与以下文件相同

Column1,Column2,Column3,Column4 


但我只需要来自 Column2,Column3,Column4 的数据,就可以使用 BCP 将数据导入 SQL 数据库。我正在使用 PowerShell 选择我想要的列并使用 BCP 导入所需的数据,但我的 powershell 执行没有错误,并且我的数据库表中没有更新数据。我可以知道如何设置BCP 将输出从 Powershell 导入数据库表。这是我的 powershell 脚本

$filePath = Get-ChildItem -Path 'D:\test\*' -Include $filename
$desiredColumn = 'Column2','Column3','Column4'

foreach($file in $filePath)
{
  write-host $file
 $test = import-csv $file | select $desiredColumn
 write-host $test
 $action = bcp <myDatabaseTableName> in $test -T -c -t";" -r"\n" -F2 -S <MyDatabase>
}



这些是 powershell 脚本的输出

D:\test\sample1.csv
@{column2=111;column3=222;column4=333} @{column2=444;column3=555;column4=666}
D:\test\sample2.csv
@{column2=777;column3=888;column4=999} @{column2=aaa;column3=bbb;column4=ccc}

【问题讨论】:

  • 您的文件显示有一个逗号 (,) 作为分隔符,但是您的 BCP 命令设置为 (-t";") 这告诉 bcp 分号字符是您的字段分隔符.文件中的实际分隔符是哪个?逗号还是分号?
  • 最后,您可以使用 BCP 跳过一列,而不是要求 powershell 重新创建数据行。你能接受这个作为答案吗?还是必须在 BCP 之前使用 powershell 转换文件?我不会使用脚本语言来处理传入的数据,我只会使用 BCP 或 SSIS。为什么不为此使用 SSIS?我有我的理由,但很好奇你为什么选择不这样做。
  • 我不熟悉 BCP 或 BCP。那么 BCP 能够胜任这项工作吗?我原来的 csv 分隔符是逗号
  • 所需的输出是我需要根据来自 CSV 的数据更新数据库表列。我的 CSV 有四列,但我的数据库表只有 3 列
  • 是的,BCP 可以胜任。 SSIS 也可以做到这一点。但是 BCP 可能更适合您,因为您似乎更喜欢编写脚本并且可能希望避免使用 gui 开发环境解决方案。

标签: sql powershell bcp


【解决方案1】:

首先,您不能更新带有bcp 的表。它用于批量加载数据。也就是说,它将插入新行或导出现有数据到平面文件中。更改现有行(通常称为更新)超出了bcp 的范围。如果这就是你需要的,你需要使用另一个工具。 Sqlcmd 工作正常,Powershell 有 Invoke-Sqlcmd 用于运行任意 TSQL 语句。

无论如何,BCP utility 的语法是出了名的棘手。据我所知,不能通过将数据作为参数传递给bcp 来批量加载数据,必须使用源文件。因此您需要保存过滤后的文件并将其名称传递给bcp

导出过滤后的 CSV 非常简单,只需记住使用-NoTypeInformation 开关,以免您将#TYPE Selected.System.Management.Automation.PSCustomObject 作为您的第一行数据。假设 bcp 参数很好(为什么要-F2?还有 Unix 换行符?)。

去除双引号需要对文件进行另一次编辑。脚本专家has a solution.

foreach($file in $filePath){
  write-host $file
  $test = import-csv $file | select $desiredColumn
  # Overwrite filtereddata.csv, should one exist, with filtered data
  $test | export-csv -path .\filtereddata.csv -NoTypeInformation
  # Remove doulbe quotes
  (gc filtereddata.csv) | % {$_ -replace '"', ''} | out-file filtereddata.csv -Fo -En ascii
  $action = bcp <myDatabaseTableName> in filtereddata.csv -T -c -t";" -r"\n" -F2 -S <MyDatabase>
}

根据您的语言环境,列分隔符可能是分号、冒号或其他内容。使用-Delimiter '&lt;character&gt;' 开关传递您需要的任何内容或更改bcp 的参数。

Erland 收到了关于批量操作的 a helpful page。另请参阅 Redgate 的 advice

【讨论】:

  • 有什么命令可以忽略export-csv中的双引号吗?
  • @HeartBreakKID 为什么?将数据括在双引号中是 CSV 标准的一部分。无论如何,没有内置功能,因此作为文本进行搜索和替换可能会起作用。您也可以通过TSQL bulk insert 试试运气。
  • 因为数据需要使用BCP导入数据库,所以不能接受任何双引号。但无论如何感谢您的指导,我设法将其更新为数据库表,但上面有双引号。
  • @HeartBreakKID 查看关于从文件中删除双引号的编辑。
【解决方案2】:

不需要先修改文件,这里有一个关于bcp如何处理引用数据的答案。

BCP in with quoted fields in source file

基本上,您需要使用 -f 选项并创建/使用格式文件来告诉 SQL 您的自定义字段分隔符(简而言之,它不再是一个单独的逗号 (,),而是现在是 (",") ...带有两个双引号的逗号。需要转义 dblquotes 和一个小技巧来处理一行中的第一个双引号。但它就像一个魅力。

另外,需要格式文件来忽略列...只需将目标列号设置为零。加载前无需修改文件。祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-14
    • 2013-12-16
    • 1970-01-01
    • 2020-06-23
    • 2021-02-27
    • 2017-08-24
    • 2022-01-22
    • 2021-04-08
    相关资源
    最近更新 更多