简体   繁体   English

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

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

I'm just learning PowerShell, I've built a script trying to import a .CSV file into my SQL Server database, and found that the following query was just appending the table. 我正在学习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)')" 
}

So in an effort to first TRUNCATE before INSERT , I've tested the following two scripts below: 因此,为了在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)')" 
}

After testing those scripts, then using my original script at the top of the page, my table returns the same number of records from the .CSV insert, but they're all blank now, and this wasn't the case prior to testing those two separate TRUNCATE scripts (the file still has the same values in each record): 测试完这些脚本之后,然后使用页面顶部的原始脚本,我的表从.CSV插入中返回相同数量的记录,但是现在它们都为空,在测试这些脚本之前不是这种情况两个单独的TRUNCATE脚本(该文件在每个记录中仍具有相同的值):

在此处输入图片说明

Querying the object from PowerShell it looks like the select-object command returns all empty records now: 从PowerShell查询对象,看起来select-object命令现在返回所有空记录

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

However, the Import-CSV, does return the values present in the file: 但是, Import-CSV确实返回文件中存在的值

Import-CSV \\TestPath\licenses_v2.csv

Testing other SQL statements to insert literal SQL strings it appears that I'm still able to write to the table using invoke-sqlcmd , but (I may be wrong) I've somehow truncated the object values that powershell is reading from the file, even though the values are still in the file. 测试其他SQL语句以插入文字SQL字符串,看来我仍然可以使用invoke-sqlcmd写入表,但是(我可能错了)我以某种方式截断了powershell从文件读取的对象值,即使这些值仍在文件中。

Do I need to restore PowerShell somehow or did i somehow alter my file system? 我需要以某种方式还原PowerShell还是以某种方式更改了文件系统?

Also, I can query the very same file from SQL using the following script, so i'm clearly able to read the values but my PowerShell script for some reason isn't able to read the values using the import-csv command: 另外,我可以使用以下脚本从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

在此处输入图片说明

Both of your methods are prone to errors are SQL injection problems because you're concatenating strings for your queries. 这两种方法都容易出错,因为SQL注入问题很容易出现,因为您要为查询串联字符串。 It would be much better to use parameterized queries (prepared statements), as it will avoid most if not all of that trouble. 使用参数化查询(预备语句)会更好,因为它将避免大部分(即使不是全部)麻烦。 But it'll be more code for you to write. 但这将为您编写更多代码。

Fortunately for you, the dbatools PowerShell module can simplify this and make it faster, safer, and more reliable with the Write-DbaDataTable function. 对您来说幸运的是, dbatools PowerShell模块可以使用Write-DbaDataTable函数来简化此过程并使其更快,更安全,更可靠。

Install the module with install-module dbatools (assuming you're using PowerShell 5/WMF5; otherwise, you'll need to follow the alternate install instructions on the website). 使用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;

If you need to truncate the table first, you can use the -Truncate switch. 如果需要首先截断表,则可以使用-Truncate开关。

The issue is caused by the missing delimiter. 该问题是由于缺少定界符引起的。

I'm using a pipe delimited CSV, when the default is comma. 我使用的是管道分隔的CSV,默认情况下为逗号。 Theres in my export script screen #1 because it creates a single object for every column. 我的导出脚本屏幕#1中有一个,因为它为每一列创建一个对象。 Which is why the headers empty, because powershell does not match any objects under those literal headers (since there's only a single header, named a combination of all.) 这就是标题为空的原因,因为powershell不匹配这些文字标题下的任何对象(因为只有一个标题,称为所有标题的组合)。

Note that Select can return headers when matched with literally nothing: 请注意,如果选择的内容与字面上没有任何内容匹配,则Select可以返回标头:

'' | Select Name,Date

Name Date
---- ----

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

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

If you specify a character other than the actual string delimiter in the file, Import-Csv cannot create objects from the CSV strings. 如果您在文件中指定的字符不是实际的字符串定界符,则Import-Csv无法从CSV字符串创建对象。 Instead, it returns the strings. 而是返回字符串。

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

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