【问题标题】:Load text into SQL Server via Powershell通过 Powershell 将文本加载到 SQL Server
【发布时间】:2011-05-25 11:53:57
【问题描述】:

我正在将从文件中逐行读取的字符数据加载到 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. 有没有更好的方法来加载文本?

我想在db中保持文本文件和行的一对一关系。

谢谢 遥控

两个答案让我在加载到 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 ('$_')"}

【问题讨论】:

    标签: sql-server powershell powershell-2.0


    【解决方案1】:

    您会得到格式错误的 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)。

    【讨论】:

    • 是的,如果他有 sql-2008,他最多可以将 1000 个值行打包到一个插入语句中。其他选项是创建临时存储过程,如 code.google.com/p/poshcodegen
    • 我正在使用 SQL 2K8R2。由于数据很短,我不需要一行一行的更多。
    【解决方案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

    【讨论】:

      【解决方案3】:

      更好的解决方案是通过 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 "插入 AA.dbo.PSFileOrder(PSFile) 值 (@xy)" -SqlParamaters @{ '@xy' = $xy} }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-03
        • 1970-01-01
        • 2015-12-12
        • 1970-01-01
        • 2014-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多