通过Powershell将文本加载到SQL Server中

时间:2010-12-14 19:10:19

标签: sql-server powershell powershell-v2.0

我正在逐行将从文件读取的字符数据加载到SQL表中。该表是:

CREATE TABLE [dbo].[PSFileOrder](
    [PSFOrder_Id] [int] IDENTITY(0,1) NOT NULL,
    [PSFile] [varchar](255) NOT NULL,
 CONSTRAINT [PK_PSFileOrder] PRIMARY KEY CLUSTERED 
(
    [PSFOrder_Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

我使用的powershell代码是

#LoadPSFile
$PSFile = "d:\ps\xx.ps1"
cls
$xy = Get-content $PSFile
$xy
foreach($xy in $xy) {invoke-sqlcmd -serverInstance localhost\sqlexpress -query "Insert AA.dbo.PSFileOrder(PSFile) Values ('$xy')"}

如果我加载的文件是:

#Filename
#The first line will always be the file name
cls
$filter = "*.*"
$folder = "\\localhost\d$\Master\men and their toys"
$filecount = (Get-ChildItem -literalpath $folder -filter $filter).Countem -literalpath $folder -filter $filter).Countem -literalpath $folder -filter $filter).Countem -literalpath $folder -filter $filter).Count
If ($filecount -lt 1) {$filecount = 0}
"There are {0} files in the {1} directory" -f $filecount, $folder

文件加载没有错误。如果文本中有单引号

"There are {0} files in the {1} d'irectory" -f $filecount, $folder

然后我会收到此错误

Invoke-Sqlcmd : Incorrect syntax near 'irectory'.
Unclosed quotation mark after the character string ' -f $filecount, $folder')
;'.
At C:\Users\RC\AppData\Local\Temp\2ed13f21-5b46-4df4-a5ee-2488c3dd5ee4.ps1:6 char:35
+ foreach($xy in $xy) {invoke-sqlcmd <<<<  -serverInstance localhost\sqlexpress -query "Insert AA.dbo.PSFileOrder(PSFile) Values ('$xy')"}
    + CategoryInfo          : InvalidOperation: (:) [Invoke-Sqlcmd], SqlPowerShellSqlExecutionException
    + FullyQualifiedErrorId : SqlError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand

我确实认为错误是由于我使用$ xy变量的单引号编写“-query”语句的方式引起的。
我的问题是:

  1. 我是否正确制作了Invoke-sqlcmd?
  2. 围绕$ xy的单引号是否有替代?
  3. 有没有更好的方法加载文字?
  4. 我想维护db中文本文件和行的一对一关系。

    由于 RC

    两个答案让我在加载到SQL之前将单引号加倍的正确路径。修改后的代码是

    #LoadPSFile
    cls
    Get-content "d:\ps\xx.ps1" | 
    Foreach-Object {$_ -replace "'", "''"} |
    ForEach-Object{invoke-sqlcmd -serverInstance localhost\sqlexpress -query "Insert AA.dbo.PSFileOrder(PSFile) Values ('$_')"}
    

3 个答案:

答案 0 :(得分:5)

您的SQL语法格式不正确。我相信快速修复是用$xy中的两个单引号替换任何单引号:

$escaped = $xy.Replace("'", "''")
invoke-sqlcmd -serverInstance localhost\sqlexpress -query "Insert AA.dbo.PSFileOrder(PSFile) Values ('$escaped')"

# or (the same but without the intermediate variable):

invoke-sqlcmd -serverInstance localhost\sqlexpress -query @"
Insert AA.dbo.PSFileOrder(PSFile) Values ('$($xy.Replace("'", "''"))')
"@

但这可能不是最好的方法。不幸的是,我不熟悉invoke-sqlcmd能力。如果它支持参数化查询,我会按照这种方式提供$xy值作为参数值(在这种情况下不需要准备$xy)。

答案 1 :(得分:2)

你必须加倍字符串

中的撇号
foreach($xy in $xy) 
{
    $xy = $xy -replace "'", "''"
    invoke-sqlcmd -serverInstance localhost\sqlexpress -query "Insert AA.dbo.PSFileOrder(PSFile) Values ('$xy')"
}

当性能成为问题时,您选择一些批量解决方案。在SQLPSX项目中 有一个模块adolib.psm1,它包含一个函数invoke-bulkcopy

link text

答案 2 :(得分:2)

更好的解决方案是通过SqlCommand.Parameters属性使用ADO.NET参数化查询。这将解决您的单撇号错误以及擦除您输入的任何可能导致sql错误的其他内容。

不幸的是,Invoke-SqlCmd不允许你这样做。但是,我修改了Chad Miller's Invoke-SqlCmd2以允许您执行此操作。在您的个人资料中包含Invoke-SqlCmd2.ps1并更改您的脚本:

  

foreach($ xy in $ xy){invoke-sqlcmd -serverInstance localhost \ sqlexpress -query“Insert AA.dbo.PSFileOrder(PSFile)Values(@xy)” - SqlParamaters @ {'@ xy'= $ xy} }