【问题标题】:Load Dataset to SQL script (in powershell)将数据集加载到 SQL 脚本(在 powershell 中)
【发布时间】:2026-01-13 16:55:01
【问题描述】:

我想从一台服务器上的 SQL Server 数据库中提取一个大型数据集,然后将该数据集包含在另一台服务器上的另一个数据库中。由于链接服务器不是一个选项,我尝试了一个 powershell 脚本,并且想要类似的东西:

$connection = 新对象 System.Data.SqlClient.SqlConnection $command = 新对象 System.Data.SqlClient.SqlCommand ... SqlDataAdapter 等也是如此 $adapter.Fill($dataset1) $connection2 = ...(到另一台服务器上的数据库) $command2 = ... 将 $dataset1 加载到 $command2 $command2.Fill($dataset2)

如何将数据集 1 加载到命令 2 中?

【问题讨论】:

    标签: sql powershell large-data-volumes


    【解决方案1】:

    您确定要将整个数据集保存在内存中吗?

    如果您只想将查询结果复制到另一个表,最好使用数据读取器以避免内存不足异常。

    # cf. http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx
    
    $SourceConnectionString      = "Data Source=localhost;Initial Catalog=source_db;Integrated Security=True"
    $DestinationConnectionString = "Data Source=localhost;Initial Catalog=Destination_db;Integrated Security=True"
    
    $tableName = "MyTable"
    $sql = "select * FROM $tableName"
    
    $sourceConnection  = New-Object System.Data.SqlClient.SQLConnection($ConnectionString)
    $sourceConnection.open()
    $commandSourceData  = New-Object system.Data.SqlClient.SqlCommand($sql,$sourceConnection)
    #$commandSourceData .CommandTimeout = '300'
    
    ps 'powershell_ise'
    $reader = $commandSourceData.ExecuteReader()
    ps 'powershell_ise'
    
    
    try
    {
        $bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $DestinationConnectionString
        $bulkCopy.DestinationTableName = $tableName
        $bulkCopy.BatchSize = 5000
        $bulkCopy.BulkCopyTimeout = 0
        $bulkCopy.WriteToServer($reader)
    }
    catch
    {
        $ex = $_.Exception
        Write-Host "Write-DataTable$($connectionName):$ex.Message"
    }
    finally
    {
        $reader.close()
    }
    

    编辑:

    在阅读 Mikes 的评论后,PowerShell 可能会展开 datareader 对象,我重试了代码替换。

    $sql = "select * FROM $tableName"
    

    $sql = "select * FROM $tableName union all select * FROM $tableName union all select * FROM $tableName union all select * FROM $tableName union all select * FROM $tableName "
    

    它仍然有效,我没有出现内存不足的异常

    $reader = $commandSourceData.ExecuteReader()
    

    在我发现问题之前,我没有理由尝试 Mikes 变体。

    第二次编辑:

    我修改了代码,添加了

    ps 'powershell_ise'
    

    之前和之后

    $reader = $commandSourceData.ExecuteReader()
    

    我没有观察到内存使用的任何变化,因此我得出结论,迈克斯关于 PowerShell 展开数据读取器对象的假设不适用。

    【讨论】:

      【解决方案2】:

      您是否考虑过 SQLBulkCopy 类? Here 是一个 powershell 函数,使用它将数据从一个数据集推送到不同的 SQL 连接。

      【讨论】:

      • 是的,SQLBulkCopy 效果很好。真正的挑战是当表非常大时 $adapter.Fill($dataset1) 处的内存不足异常。
      • 如果您传递数据读取器,则不必将记录下拉到数据表中。 SQLBulkCopy 将“流式传输”它们。在 PowerShell 中,您可能需要执行以下操作: $bulkCopy.WriteToServer($cmd.ExecuteReader()) 即不要提前调用 ExecuteReader 方法,因为 PowerShell 喜欢展开数据读取器对象。
      • @Mike 你确定吗?我正在玩一个 400425 行的表,并且看不出调用 ExecuteReader 的两种模式之间的区别。使用数据表,每三次试验都会出现内存不足异常。
      • 我已经复制了数百万行表,没有内存问题(使用我的笔记本电脑)。
      • @Mike 当 PowerShell 展开数据读取器时,我必须看到在 $reader = $commandSourceData.ExecuteReader() 之前和之后使用 ps 的差异。请参阅我的代码的编辑。我没有任何差异。
      最近更新 更多