【发布时间】:2019-06-25 09:42:22
【问题描述】:
假设我有一个包含这些列的 SQL 表:
[服务器名称],[SESSION_ID],[SESSION_SPID]
我正在尝试将存储在数据表 ($dmvResult) 中的值复制到上面的 SQL 表 ($Table)
$dmvResult = DMV_Query 'SELECT [SESSION_ID]
,[SESSION_SPID]
FROM $SYSTEM.DISCOVER_SESSIONS';
$ConnectionString ='Data Source=$server; Database=$database; Trusted_Connection=True;'
$bulkCopy = new-object Data.SqlClient.SqlBulkCopy($ConnectionString)
$bulkCopy.DestinationTableName=$Table
$bulkCopy.WriteToServer($dmvResult)
虽然复制成功完成,但存在一个问题:它是按位置复制,而不是按列名匹配。换句话说,复制的列没有被映射并复制到相同的列。
[SESSION_ID] 被复制到 [server_name] 并且 [SESSION_SPID] 正在复制到 [SESSION_ID]
如何告诉 bulkCopy 匹配列并进行复制?
结果副本应该是 [server_name] 为空,因为它不是从 DMV 查询中选择的。
我在这个帖子中找到了一个巧妙的解决方案:
https://stackoverflow.com/a/20045505/8397835
但我不知道如何将其转换为我的 powershell 代码:
var meta = definition.Context.Mapping.GetMetaType(typeof(T));
foreach (var col in meta.DataMembers)
{
copy.ColumnMappings.Add(col.Member.Name, col.MappedName);
}
编辑:foreach column.ColumnName 输出
编辑2: 我试过这个:
$dmvResult.Columns |%{$_.Name}
它不输出任何东西。
在您说 $dmvResult 数据表必须为空之前,请解释一下这实际上如何工作并复制数据?
$bulkCopy.ColumnMappings.Add('SESSION_ID', 'SESSION_ID')
$bulkCopy.ColumnMappings.Add('SESSION_SPID', 'SESSION_SPID')
$bulkCopy.WriteToServer($dmvResult)
由于某种原因,它也将其输出到控制台:
所以数据表 $dmvResult 被清楚地填充了。
我希望不要像这样为每一列定义映射:
$bulkCopy.ColumnMappings.Add('SESSION_SPID', 'SESSION_SPID')
取而代之的是这样的自动选项:
foreach ($column in $dmvResult.Columns) { $bulkCopy.ColumnMappings.Add($column.ColumnName, $column.ColumnName)}
但这会引发异常:
使用“1”个参数调用“WriteToServer”的异常:“给定的 ColumnMapping 与源中的任何列都不匹配,或者 目的地。”
【问题讨论】:
-
当然是建立一个列映射。这就像 bulkCopy 类中唯一的其他方法。 Here is how you would do it in C# 我不知道如何为你翻译成 PS。可能是
$bulkCopy.ColumnMappings.Add($col1, $col2)之类的? -
@JacobH 该死,我希望有一个自动映射选项。但看来我必须明确定义列:/
-
@JacobH 我用我认为是自动映射的答案的链接更新了我的线程,尽管我不确定如何将它从 c# 转换为 powershell
-
哦,有自动映射——它会自动按序号位置映射所有列。是的,这很愚蠢,它可以专门处理
DataTable的情况,但事实并非如此。foreach ($column in $dmvResult.Columns) { $bulkCopy.ColumnMappings.Add($column.ColumnName, $column.ColumnName) }应该这样做。 (免责声明:未经测试。) -
在循环中加入
Write-Output $column.ColumnName来调试它。列名可能不是您所期望的,特别是如果(我怀疑)这是一个从 SSAS 产生结果的查询,它有修饰列名的趋势。还要检查表是否正确,如果您的数据库使用区分大小写的排序规则,则大小写是否匹配。最后,请记住[name]只是name的转义版本——括号实际上不是列名的一部分,所以如果你的表实际上有[SESSION_SPID]作为列名,那将是错误的。
标签: sql-server powershell dmv