Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 使用PowerShell将大量AD数据插入SQL server_Sql Server_Powershell_Active Directory - Fatal编程技术网

Sql server 使用PowerShell将大量AD数据插入SQL server

Sql server 使用PowerShell将大量AD数据插入SQL server,sql-server,powershell,active-directory,Sql Server,Powershell,Active Directory,我有一个PowerShell脚本,它可以提取140多万行数据,并将其保存到一个巨大的CSV文件中,然后导入SQL server。我认为有一种方法可以让PowerShell直接将数据插入SQL server,但我不确定如何插入 我担心的一点是,我不想将AD结果缓冲到内存中,然后再将其写入。我宁愿把它们成批地写上1000个左右,这样内存消耗就会减少。获取1000条记录,保存到SQL server,然后重复 我看到了一些关于如何让PowerShell写入SQL server的文章,但它们似乎要么一次写

我有一个PowerShell脚本,它可以提取140多万行数据,并将其保存到一个巨大的CSV文件中,然后导入SQL server。我认为有一种方法可以让PowerShell直接将数据插入SQL server,但我不确定如何插入

我担心的一点是,我不想将AD结果缓冲到内存中,然后再将其写入。我宁愿把它们成批地写上1000个左右,这样内存消耗就会减少。获取1000条记录,保存到SQL server,然后重复

我看到了一些关于如何让PowerShell写入SQL server的文章,但它们似乎要么一次写入所有数据,要么一次写入一条记录,这两种方法对我来说都是低效的

这是我必须查询的PowerShell脚本

# the attributes we want to load
$ATTRIBUTES_TO_GET = "name,distinguishedName"

# split into an array
$attributes = $ATTRIBUTES_TO_GET.split(",")

# create a select string to be used when we want to dump the information
$selectAttributes = $attributes | ForEach-Object {@{n="AD $_";e=$ExecutionContext.InvokeCommand.NewScriptBlock("`$_.$($_.toLower())")}}

# get a directory searcher to search the GC
[System.DirectoryServices.DirectoryEntry] $objRoot = New-Object System.DirectoryServices.DirectoryEntry("GC://dc=company,dc=com")
[System.DirectoryServices.DirectorySearcher] $objSearcher = New-Object System.DirectoryServices.DirectorySearcher($objRoot)

# set properties
$objSearcher.SearchScope = "Subtree"
$objSearcher.ReferralChasing = "All"

# need to set page size otherwise AD won't return everything
$objSearcher.PageSize = 1000

# load the data we want
$objSearcher.PropertiesToLoad.AddRange($attributes)

# set the filter
$objSearcher.Filter = "(&(objectClass=group)(|(name=a*)(name=b*)))"

# get the data and export to csv
$objSearcher.FindAll() | select -expandproperty properties | select $selectAttributes | export-csv -notypeinformation -force "out.csv"

我使用
Out DataTable
将我的对象数组转换为
DataTable
对象类型,然后使用
Write DataTable
将其大容量插入数据库(
Write DataTable
使用
SqlBulkCopy
执行此操作)

这方面的注意事项/问题(SqlBulkCopy可能是一个麻烦的疑难解答):

  • 确保属性的类型正确(varchar/nvarchar为string,任何整数值为int,只要格式正确,dateTime可以是string,SQL可以解析它)
  • 确保属性有序并与要插入的表对齐,包括自动填充的任何字段(递增ID键、RunDt等)
输出数据表:

写入数据表:

用法

如果我继续你的例子,跳过CSV,我会这样做。。。用下面的代码替换最后两行(假设对象属性与表完全对齐,SQL server名称为
SQL-server-1
,数据库名称为
org
,表名称为
employees
):


看看你的代码,它看起来像你来自.NET或一些基于.NET的语言。您是否听说过cmdlet/?这将大大简化您的工作

就SQL连接而言,PowerShell没有任何本机支持。微软已经成功了!您只需要安装SQL Server就可以获得它们。。。。这有点令人沮丧,因为SQL太重了,不是每个人都想安装它。使用.NET仍然是可能的,只是它不是很快或者很漂亮。我不会在这里提供有关cmdlet的建议,您可以在谷歌上搜索。至于.NET,我将首先阅读一些关于名称空间的文档以及一些关于主题的文档

最后,正如您所说的,尝试避免RAM过载是一个好主意。这里最重要的一点是尽量将整个脚本简化为一个广告查询。这样可以避免在一个查询和下一个查询之间更改数据的麻烦场景。我认为最好的方法是将结果直接保存到文件中。一旦你有了它,你就可以直接从你的文件中插入到表中。缺点是它不允许多个广告属性。至少我不认为SqlBulkCopy会允许这样做

Get-ADUser "SomeParamsHere" | Out-File ADOutput.txt
如果您必须拥有多个广告属性,并且仍然希望将RAM使用率保持在最低限度……那么,我尝试了一个脚本,该脚本可以正常工作,但进行了一些调用,将读取整个文件,这就破坏了整个目的。您最好的选择可能是将每个属性保存到一个单独的文件中,然后执行整个写数据库操作。例如:

New-Item Name.txt
New-Item DistinguishedName.txt

Get-ADUser "SomeParamsHere" -Properties "Name,DistinguishedName" | Foreach {
    Add-Content -Path "Name.txt" -Value "$_.Name"
    Add-Content -PassThru "DistinguishedName.txt" -Value "$_.DistinguishedName"
}

将结果存储在变量的最后一行代码中,而不是将其导出为csv。
然后创建您想要的大小的组。
在nferrell的回答中使用Out DataTable和Write DataTable Write to SQL-links

$res = $objSearcher.FindAll() | select -expandproperty properties | select 
$selectAttributes 
$counter = [pscustomobject] @{ Value = 0 }
#create groups with 1000 entries each 
$groups = $res | Group-Object -Property { [math]::Floor($counter.Value++ / 1000) }
foreach ($group in $groups){
    #convert to data table
    $dt = $group.group | Out-DataTable
    $dt | Write-DataTable -Database DB -ServerInstance SERVER -TableName TABLE 
}

`你把这件事弄得太复杂了。 如果我正确阅读了您的代码,您希望所有组都以“a”或“b”开头

# the attributes we want to export
$attributes = 'name', 'distinguishedName'

Import-Module ActiveDirectory

Get-ADGroup -Filter {(name -like "a*") -or (name -like "b*")} -SearchBase 'dc=company,dc=com' |
    select $attributes | Export-Csv -NoTypeInformation -Force "out.csv"
不要在最后使用
Export Csv
,只需将输出通过管道传输到创建SQL行的命令即可。通过管道化对象(而不是将其分配给变量),您可以让PowerShell高效地处理它们(它将在对象进入时开始处理对象,而不是缓冲所有对象)


很遗憾,我无法帮助您完成SQL部分。

请考虑分批使用SqlBulkCopy。我认为a是最有效的。你为什么会不这么认为?@DanGuzman但我如何使用
System.DirectoryServices.SearchResultCollection
对象分批完成它呢?我能想到的唯一方法是迭代搜索结果集合,在记录的X个之后进行批量SQL插入?@AnsgarWiechers我并不反对。我就是不知道如何使用
SearchResultCollection
对象进行批量插入,而不必将整个集合加载到内存中。但是第一行,
$set=…
是否会首先将所有内容加载到内存中?难道没有办法只将X行加载到内存中,写入SQL,然后加载下X行吗?如果对AD的查询正在提取所有内容,那么它已经加载到内存中了。您需要收紧查询,否则这是一个无关紧要的问题。我已经将我的更新为一个用try-catch语句包装的单行程序,因此它会立即加载到数组中,转换为datatable,然后批量插入到数据库中。考虑到您的
$objSearcher.PageSize=1000
位已经受到限制,也许可以将其转换为在循环中一次批量插入1000条记录?我会说,我使用相同的方法一次将75000多行加载到SQL中,其中许多是nvarchar(最大)字段。它可以处理很大的负载,我认为你可以节省大量的时间一次做更大的块我听说过
Get ADUser
,但我认为.NET更快、更高效。不是这样吗?如果我先保存到文件,那么这是一个多步骤的过程:获取数据,写入fi
# the attributes we want to export
$attributes = 'name', 'distinguishedName'

Import-Module ActiveDirectory

Get-ADGroup -Filter {(name -like "a*") -or (name -like "b*")} -SearchBase 'dc=company,dc=com' |
    select $attributes | Export-Csv -NoTypeInformation -Force "out.csv"