CREATE TABLE dbo.StructuredTest (ID int IDENTITY,
SomeString varchar(10),
SomeInt int);
GO
INSERT INTO dbo.StructuredTest (SomeString,
SomeInt)
VALUES('abc',1),
('def',2),
('xyz',1);
现在我们要传递一个 ID 列表 int 。我们需要一个表类型,例如:
CREATE TYPE dbo.Ints AS table(IntValue int);
然后我们可以使用 PowerShell 中的以下脚本将表类型作为类型传递 dbo.Ints :
$Query = 'SELECT * FROM dbo.StructuredTest ST WHERE EXISTS (SELECT 1 FROM @TableVariable TV WHERE TV.Intvalue = ST.ID);'
$IDs = @()
$IDs += [PSCustomObject]@{Intvalue = 1}
$IDs += [PSCustomObject]@{Intvalue = 2}
$DT = ConvertTo-DbaDataTable -InputObject $IDs
$TableVariable = New-DbaSqlParameter -ParameterName TableVariable -SqlDbType Structured -Value $DT -TypeName 'dbo.Ints'
Invoke-DbaQuery -SqlInstance 'SandboxServer' -Database Sandbox -Query $Query -SqlParameter $TableVariable
$runIDs = @(1, 2, 3)
# establish connection
$connection = [System.Data.SqlClient.SqlConnection]::new("connection string goes here")
$connection.Open()
# define the first part of the command text
$cmdTextPreamble = @'
DECLARE @RunIDsToDelete TABLE (RunID INT);
INSERT INTO @RunIDsToDelete (RunID)
VALUES
'@
# create a command object
$cmd = [System.Data.SqlClient.SqlCommand]::new()
$cmd.Connection = $connection
# now construct the final command text, one insertion at a time
$cmdText = $cmdTextPreamble
for ($i = 0; $i -lt $runIDs.Count; $i++) {
# calculate the next parameter name
$paramName = "@runID${i}"
# add the parameterized value set to the command text
$cmdText += "(${paramName}),"
# and bind the corresponding value to the parameter name
$cmd.Parameters.AddWithValue($paramName, $runIDs[$i]) |Out-Null
}
# remove trailing `,` from the command text and update the $cmd object
$cmd.CommandText = $cmdText.TrimEnd(',')
# execute insert command
$rowCount = $cmd.ExecuteNonQuery()
Write-Host "Inserted ${rowCount} rows into table"
While the broken behavior is fixed in PowerShell (Core) 7 v7.3+ , where getting the old, broken behavior back now requires opt-in via $PSNativeCommandArgumentPassing = 'Legacy' , this opt-in isn't actually necessary for sqlcmd.exe , because it is on an exception list of known executables to which the old behavior continues to be applied automatically in the default $PSNativeCommandArgumentPassing mode, 'Windows' - see the docs for the complete list.