Sql server 在文本文件中查找特定文本并插入到SQL

Sql server 在文本文件中查找特定文本并插入到SQL,sql-server,powershell,Sql Server,Powershell,我正在尝试稍微优化我的Powershell脚本。 我有很多日志(文本)文件,我需要在其中的内容中搜索特定的文本条目。 如果找到了条目,我需要脚本以插入sql数据库的方式触发 这就是我现在所拥有的: $tidnu = (Get-Date -f dd.MM.yyyy) $Text = "ERROR MESSAGE STACK" $PathArray = @() $NodeName = "SomeName" $Logfil = "SomeLogFile" Get-ChildItem $Path -F

我正在尝试稍微优化我的Powershell脚本。 我有很多日志(文本)文件,我需要在其中的内容中搜索特定的文本条目。 如果找到了条目,我需要脚本以插入sql数据库的方式触发

这就是我现在所拥有的:

$tidnu = (Get-Date -f dd.MM.yyyy)
$Text = "ERROR MESSAGE STACK"
$PathArray = @()
$NodeName = "SomeName"
$Logfil = "SomeLogFile"

Get-ChildItem $Path -Filter "*ORA11*.log" |
Where-Object { $_.Attributes -ne "Directory"} |
  ForEach-Object {
     If (Get-Content $_.FullName | Select-String -Pattern $Text)
     {
        $PathArray += $_.FullName
        $cmd.commandtext = "INSERT INTO ErrorTabel (Datotid, Nodename, Logfil, ErrorFound) VALUES('{0}','{1}','{2}','{3}')" -f $tidnu, $NodeName, $Logfil, "Yes"
        $cmd.ExecuteNonQuery()
     }
     else
     {                      
        $cmd.commandtext = "INSERT INTO ErrorTabel (Datotid, Nodename, ErrorFound) VALUES('{0}','{1}','{2}')" -f $tidnu, $NodeName, "No"
        $cmd.ExecuteNonQuery()
     }
  }
这是正常的,但当我需要移动到另一个日志文件名时,我只是用不同的输入再次生成相同的代码。 我想做的是使用一个数组和一个foreach循环,这样我就可以在一个数组中指定所有日志文件,如:

$LogArray = @(Log1.log, log2.log, log3.log)
并指定所有节点名称,如:

$NodeArray = @(Node1, Node2, Node3)
然后创建一个foreach循环,该循环将逐个遍历日志文件并插入数据库,每次循环运行时它都与nodename匹配

有人能帮我做到这一点吗?我知道应该怎么做,但我不知道怎么写代码。我们将不胜感激

编辑:

好的,这就是我现在所知道的,但我不确定把它们放在一起是否正确。这给了我一些奇怪的结果

$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Data Source=PCDK03918;Initial Catalog=Rman;Integrated Security=SSPI;"
$conn.open()
$cmd = New-Object System.Data.SqlClient.SqlCommand
$cmd.connection = $conn

$tidnu = (Get-Date -f dd.MM.yyyy)
$Path = "C:\RMAN"
$Text = "ERROR MESSAGE STACK"


$nodes = @{
  'NodeName1' = 'Node1log1.log', 'Node1log2.log', 'Node1log3.log'
  'NodeName2' = 'Node2log1.log', 'Node2log2.log'
}

foreach ($NodeName in $nodes.Keys) {
foreach ($Logfil in $nodes[$NodeName]) {


Get-ChildItem $Path -Filter "*.log" |

ForEach-Object {
 If (Get-Content $_.FullName | Select-String -Pattern $Text)
 {       
    $cmd.commandtext = "INSERT INTO Error (Datotid, Nodename, Logfil, Error) VALUES('{0}','{1}','{2}','{3}')" -f $tidnu, $NodeName, $Logfil, "Yes"
    $cmd.ExecuteNonQuery()
 }
 else
 {                      
    $cmd.commandtext = "INSERT INTO Error (Datotid, Nodename, Logfil, Error) VALUES('{0}','{1}','{2}','{3}')" -f $tidnu, $NodeName, $Logfil, "No"
    $cmd.ExecuteNonQuery()
   }
  }  
 }
}
$conn.close()
我已经在文件夹中创建了$nodes中提到的日志文件,并将“错误消息堆栈”放入Node1log1.log和Node1log2.log中。其余日志文件中没有“错误消息堆栈”

但数据库中的结果很奇怪。对于内部没有“错误消息堆栈”的日志文件,它表示Error=Yes;对于某些行下面的相同日志文件,它表示Error=no。加上它插入了两行和所有的一切,它没有按预期做

可能是因为我的

Get-ChildItem $Path -Filter "*.log" |
使用*.log是否有误

还是我在这方面完全错了

再次编辑:

不知道我昨天在想什么,但我相信我现在已经解决了

Get-ChildItem $Path -Filter "*.log" |
当然不行

Get-ChildItem $Path -Filter $logfil |
提供了更多的意义,现在我的数据库输出看起来更加正确


@Ansgar Wiechers-谢谢你为我指明了正确的方向。我从中学到了很多

考虑为此使用哈希表:

$logs=@{
'Log1.log'='Node1'
'Log2.log'='Node2'
'Log3.log'='Node3'
}
这样,您可以像这样迭代日志:

foreach($logs.key中的Logfil){
$NodeName=$logs[$Logfil]
...
}
如果每个节点名有多个日志文件,则反转映射并将日志文件名存储在数组中会更有效:

$nodes=@{
'Node1'='Log1.log','Log2.log','Log3.log'
'Node2'='Log4.log','Log5.log'
}
然后可以使用嵌套循环处理日志文件,如下所示:

foreach($nodes.Keys中的NodeName){
foreach($nodes[$NodeName]中的Logfil){
...
}
}
您应该能够将管道安装到任一循环中,而无需进一步修改

编辑:作为一种优化,您可以这样做,以避免在外部循环的每次迭代中不必要地获取日志:

$logs=Get ChildItem$Path-Filter'*.log'
foreach($nodes.Keys中的NodeName){
$logs |?{$nodes[$NodeName]-包含$|.Name}|%{
...
}
}

谢谢您的帮助。我不确定我是否完全明白。假设我有两个不同的节点名称,比如:节点名称1和节点名称2。NodeName1有2个日志文件连接到它。NodeName2有3个日志文件连接到它。所有日志文件都有不同的名称。我如何结合我现在所拥有的和您的建议来查看这5个日志文件?我是新来的编码,所以请如果你可以,尝试更具体。我真的很感激。谢谢你的时间和帮助。请参阅更新的第一篇帖子。@G.T抱歉,我没有意识到日志是由
Get ChildItem
获取的,但看起来您已经找到了解决方案。不过,我建议使用稍微不同的方法来读取/过滤日志,以避免循环中不必要的操作。请参阅更新的答案。再次感谢。我两种方法都试过了。而且他们都做得很好。我可以将所有不同的节点名及其对应的日志文件添加到数组中。它在数据库中给出了一个非常好的结果。此外,现在向脚本添加新节点和日志也非常容易。再次感谢你的帮助。我从中学到了很多。