繁体   English   中英

缺少将数组变量从csv文件传递到invoke-sqlcmd插入语句的值?

[英]Missing values passing array variables from csv file to invoke-sqlcmd insert statement?

我正在学习PowerShell,我已经构建了一个脚本,试图将.CSV文件导入到我的SQL Server数据库中,发现以下查询只是在追加表。

$database = 'DATABASE'
$server = 'SERVER'
$table = 'TABLE'
Import-CSV \\TESTPATH\licenses_v2.csv  | 
ForEach-Object { 
Invoke-Sqlcmd -Database $database -ServerInstance $server -Query "insert into $table VALUES ('$($_.FirstName)','$($_.LastName)','$($_.Department)','$($_.Title)')" 
}

因此,为了在INSERT之前先进行TRUNCATE ,我在下面测试了以下两个脚本:

$database = 'DATABASE'
$server = 'SERVER'
$table = 'TABLE'
Import-CSV \\TESTPATH\licenses_v2.csv | 
ForEach-Object { Invoke-Sqlcmd -Database $database -ServerInstance $server -Query "truncate table $table; insert into $table VALUES ('$($_.FirstName)','$($_.LastName)','$($_.Department)','$($_.Title)')" 
}

$database = 'DATABASE'
$server = 'SERVER'
$table = 'TABLE'
Invoke-Sqlcmd -Database $database -ServerInstance $server -Query "truncate table $table"
Import-CSV \\TESTPATH\licenses_v2.csv | 
ForEach-Object { Invoke-Sqlcmd -Database $database -ServerInstance $server -Query "insert into $table VALUES ('$($_.FirstName)','$($_.LastName)','$($_.Department)','$($_.Title)')" 
}

测试完这些脚本之后,然后使用页面顶部的原始脚本,我的表从.CSV插入中返回相同数量的记录,但是现在它们都为空,在测试这些脚本之前不是这种情况两个单独的TRUNCATE脚本(该文件在每个记录中仍具有相同的值):

在此处输入图片说明

从PowerShell查询对象,看起来select-object命令现在返回所有空记录

import-csv \\TestPath\licenses_v2.csv | select-object FirstName,Department,Title

但是, Import-CSV确实返回文件中存在的值

Import-CSV \\TestPath\licenses_v2.csv

测试其他SQL语句以插入文字SQL字符串,看来我仍然可以使用invoke-sqlcmd写入表,但是(我可能错了)我以某种方式截断了powershell从文件读取的对象值,即使这些值仍在文件中。

我需要以某种方式还原PowerShell还是以某种方式更改了文件系统?

另外,我可以使用以下脚本从SQL查询相同的文件,因此我显然能够读取值,但是由于某些原因,我的PowerShell脚本无法使用import-csv命令读取值:

CREATE TABLE #TempTable(
    [FirstName] [varchar](50) NULL,
    [LastName] [varchar](50) NULL,
    [Department] [varchar](150) NULL,
    [Title] [varchar](150) NULL
) 
   BULK INSERT #TempTable
    FROM '\\TestPath\licenses_v2.csv'
    WITH
(
  FIRSTROW = 2,
  DATAFILETYPE='char', 
  FIELDTERMINATOR = '|',
  ROWTERMINATOR = '\n',
  TABLOCK,
  KEEPNULLS -- Treat empty fields as NULLs.
)
go
select * from #TempTable

在此处输入图片说明

这两种方法都容易出错,因为SQL注入问题很容易出现,因为您要为查询串联字符串。 使用参数化查询(预备语句)会更好,因为它将避免大部分(即使不是全部)麻烦。 但这将为您编写更多代码。

对您来说幸运的是, dbatools PowerShell模块可以使用Write-DbaDataTable函数来简化此过程并使其更快,更安全,更可靠。

使用install-module dbatools (假设您使用的是PowerShell 5 / WMF5;否则,您需要按照网站上的备用安装说明进行操作)。

import-module dbatools;
$database = 'DATABASE';
$server = 'SERVER';
$table = 'TABLE';
$MyData = import-csv \\TESTPATH\licenses_v2.csv | select-object FirstName,Department,Title;
Write-DbaDataTable -sqlinstance $server -database $database -table $table -inputobject $MyData;

如果需要首先截断表,则可以使用-Truncate开关。

该问题是由于缺少定界符引起的。

我使用的是管道分隔的CSV,默认情况下为逗号。 我的导出脚本屏幕#1中有一个,因为它为每一列创建一个对象。 这就是标题为空的原因,因为powershell不匹配这些文字标题下的任何对象(因为只有一个标题,称为所有标题的组合)。

请注意,如果选择的内容与字面上没有任何内容匹配,则Select可以返回标头:

'' | Select Name,Date

Name Date
---- ----

要解决此问题,只需使用Import-Csv -Delimiter '|'

请参阅https://docs.microsoft.com/zh-cn/powershell/module/microsoft.powershell.utility/import-csv?view=powershell-6#optional-parameters

如果您在文件中指定的字符不是实际的字符串定界符,则Import-Csv无法从CSV字符串创建对象。 而是返回字符串。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM