缺少将数组变量从 csv 文件传递到 invoke-sqlcmd 插入语句的值?
Missing values passing array variables from csv file to invoke-sqlcmd insert statement?
我刚刚在学习 PowerShell,我构建了一个脚本,试图将 .CSV
文件导入我的 SQL 服务器数据库,发现以下查询只是附加了 table.
$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)')"
}
测试完这些脚本后,然后在页面顶部使用我的原始脚本,我的 table returns 来自 .CSV
插入的相同数量的记录,但是它们现在都是空白,在测试这两个单独的 TRUNCATE
脚本之前情况并非如此(该文件在每个记录中仍然具有相同的值):
从 PowerShell 查询对象它看起来像 select-object 命令return现在所有空记录:
import-csv \TestPath\licenses_v2.csv | select-object FirstName,Department,Title
但是,Import-CSV 确实return文件中存在的值:
Import-CSV \TestPath\licenses_v2.csv
测试其他 SQL 语句以插入文字 SQL 字符串看来我仍然可以使用 invoke-sqlcmd
写入 table,但是(我可能是错误的)我以某种方式截断了 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 module can simplify this and make it faster, safer, and more reliable with the 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;
如果需要先截断 table,可以使用 -Truncate
开关。
问题是由缺少分隔符引起的。
我使用的是竖线分隔的 CSV,默认为逗号。在我的导出脚本屏幕 #1 中有,因为它为每一列创建了一个 object。这就是 headers 为空的原因,因为 powershell 不匹配那些文字 headers 下的任何 objects(因为只有一个 header,命名为所有的组合.)
请注意,Select 可以 return header 与几乎没有匹配时:
'' | Select Name,Date
Name Date
---- ----
要修复,只需使用 Import-Csv -Delimiter '|'
If you specify a character other than the actual string delimiter in the file, Import-Csv cannot create objects from the CSV strings. Instead, it returns the strings.
我刚刚在学习 PowerShell,我构建了一个脚本,试图将 .CSV
文件导入我的 SQL 服务器数据库,发现以下查询只是附加了 table.
$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)')"
}
测试完这些脚本后,然后在页面顶部使用我的原始脚本,我的 table returns 来自 .CSV
插入的相同数量的记录,但是它们现在都是空白,在测试这两个单独的 TRUNCATE
脚本之前情况并非如此(该文件在每个记录中仍然具有相同的值):
从 PowerShell 查询对象它看起来像 select-object 命令return现在所有空记录:
import-csv \TestPath\licenses_v2.csv | select-object FirstName,Department,Title
但是,Import-CSV 确实return文件中存在的值:
Import-CSV \TestPath\licenses_v2.csv
测试其他 SQL 语句以插入文字 SQL 字符串看来我仍然可以使用 invoke-sqlcmd
写入 table,但是(我可能是错误的)我以某种方式截断了 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 module can simplify this and make it faster, safer, and more reliable with the 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;
如果需要先截断 table,可以使用 -Truncate
开关。
问题是由缺少分隔符引起的。
我使用的是竖线分隔的 CSV,默认为逗号。在我的导出脚本屏幕 #1 中有,因为它为每一列创建了一个 object。这就是 headers 为空的原因,因为 powershell 不匹配那些文字 headers 下的任何 objects(因为只有一个 header,命名为所有的组合.)
请注意,Select 可以 return header 与几乎没有匹配时:
'' | Select Name,Date
Name Date
---- ----
要修复,只需使用 Import-Csv -Delimiter '|'
If you specify a character other than the actual string delimiter in the file, Import-Csv cannot create objects from the CSV strings. Instead, it returns the strings.