从Powershell

问题描述

无法弄清楚我在哪里出错,存储过程中的TVP引用了@asn,但我不断收到以下错误/警告,我已经尝试了所有方法,但在此没有进一步的详细信息sql服务器日志,感谢任何帮助。

PowerShell函数

Function Execute-Procedure {
    Param(
        [Parameter(Mandatory=$true)][array]$p
    )
    Process {
        $connectionString = "Server=;Database=;User ID=;Password=;Trusted_Connection=True"
        $conn = New-Object System.Data.sqlClient.sqlConnection $connectionString

        $cmd = New-Object System.Data.sqlClient.sqlCommand
        $cmd.Connection = $conn
        $cmd.CommandTimeout = 0
        $pvar = ("V-" + $p.ToString())
        $sqlParam = New-Object System.Data.sqlClient.sqlParameter("@asn",$pvar)
        $null = $cmd.Parameters.Add($sqlParam,[System.Data.sqlDbType]::NVarChar)
        $cmd.CommandText = "EXEC tsp_insert_asn @asn"
        
        try {
            $conn.open()
            $cmd.ExecuteNonQuery() | Out-Null
        } catch [Exception] {
            Write-Warning $_.Exception.Message
        } finally {
            $conn.dispose()
            $cmd.dispose()
        }
    }
}

存储过程:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER  PROCEDURE [dbo].[tsp_insert_asn]
    @asn AS [dbo].[tvp_asn] READONLY
AS
BEGIN   
    INSERT INTO [dbo].[asn]
        SELECT  asn_id,name,size,location,GETDATE()
        FROM @asn;
END

错误

警告:参数化查询'(@asn nvarchar(4000))EXEC tsp_insert_asn @asn'需要未提供的参数'@asn'。

解决方法

首先使用与用户定义类型(UDT)相同的架构创建一个数据表:

$DataTable = New-Object -TypeName System.Data.DataTable
$DataColumn = New-Object -TypeName System.Data.DataColumn -ArgumentList 'asn_id',([String])
$DataTable.Columns.Add($DataColumn)
$DataColumn = New-Object -TypeName System.Data.DataColumn -ArgumentList 'name',([String])
$DataTable.Columns.Add($DataColumn)
$DataColumn = New-Object -TypeName System.Data.DataColumn -ArgumentList 'size',([String])
$DataTable.Columns.Add($DataColumn)
$DataColumn = New-Object -TypeName System.Data.DataColumn -ArgumentList 'location',([String])
$DataTable.Columns.Add($DataColumn)

请注意,我将ever列创建为string。不要那样做!您的列应与UDT列的数据类型匹配。在这一点上,我不记得要使用SQL数据类型还是.Net数据类型,但是我敢肯定,如果它不起作用,它将很明显。

现在从数组中填充数据表。

foreach ($i in $p) {
    $DataRow = $DataTable.NewRow()
    $DataRow.'asn_id'   = $i.'asn_id'  
    $DataRow.'name'     = $i.'name'    
    $DataRow.'size'     = $i.'size'    
    $DataRow.'location' = $i.'location'
    $DataTable.Rows.Add($DataRow)
}

现在使用数据表作为Structured数据类型的参数值连接并执行存储过程。

$conn = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $connectionString
$cmd = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList $conn
$cmd.CommandType = [System.Data.CommandType]::StoredProcedure
$cmd.CommandText = 'tsp_insert_asn'
$cmd.Parameters.Add("@asn",[System.Data.SqlDbType]::Structured).Value = $DataTable

try {
    $conn.Open()
    $null = $cmd.ExecuteNonQuery()
}
finally {
    $conn.Close()
}