0

我刚刚学习 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)')" 
}

因此,为了首先尝试TRUNCATEINSERT我测试了以下两个脚本:

$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

在此处输入图像描述

4

2 回答 2

0

您的两种方法都容易出错,都是 SQL 注入问题,因为您正在为查询连接字符串。使用参数化查询(准备好的语句)会更好,因为它可以避免大部分(如果不是全部)麻烦。但这将是您编写的更多代码。

幸运的是,dbatoolsPowerShell 模块可以简化这一过程,并通过该功能使其更快、更安全、更可靠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开关。

于 2018-04-10T20:11:46.390 回答
0

该问题是由缺少分隔符引起的。

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

请注意,当与任何内容匹配时,Select 可以返回标头:

'' | Select Name,Date

Name Date
---- ----

要修复,只需使用Import-Csv -Delimiter '|'

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

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

于 2018-04-12T00:35:40.323 回答