使用PowerShell执行并发过程

时间:2019-01-02 16:09:15

标签: powershell

我想设置一个新的PowerShell脚本,该脚本同时调用我的数据库存储过程。我目前有一个具有Job_ID列和Code列的Control表。控制表中的代码值可能有多个Job_ID。基于我在PowerShell中传递的代码值以及日期,我希望PowerShell触发存储过程,该存储过程期望将“ Job_ID”和“ MyDate”作为输入参数。

仅供参考,我正在使用PowerShell和SQL Server 2016。

PS C:\PowerShell> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      -1     -1

以下是一些示例数据供您参考:

CREATE TABLE control_table(JOB_ID INT, CODE VARCHAR(5));
INSERT INTO control_table(1, 'ABC');
INSERT INTO control_table(2, 'ABC');
INSERT INTO control_table(3, 'ABC');
INSERT INTO control_table(1, 'DEF');
INSERT INTO control_table(1, 'GHI');

CREATE PROCEDURE myschema.run_job (@JOB_ID INT, @MyDate DATE)
AS
BEGIN
-- Do Something
END

当我通过传递“ ABC”作为代码运行PowerShell脚本时,它应该通过读取控制表并发执行所有三个作业。

类似

.\test.ps1 –MyCode “ABC” –Dt “12/27/2018”

2 个答案:

答案 0 :(得分:0)

作为作业的替代方法,可以使用内置SQL客户端的异步方法。下面是示例代码。我假设您已经有一些“ run_job”过程,可以通过id执行其他过程(工作)。

$code = "ABC"

$date = "2018-12-31"

$jobs = @{} # this  will store results of async jobs

$str = "Server = YourServer; Database = YourDB; Integrated Security = True;"

#-------- 

function Async-Sql { param($connStr, $sql, [switch]$GetDataTable)

 $conn = New-Object System.Data.SqlClient.SqlConnection $str
 $cmd = $conn.CreateCommand()
 $conn.Open()
 $cmd.CommandText = $sql

 if($GetDataTable) { 
   $dt = New-Object System.Data.DataTable "result"
   $r = $cmd.ExecuteReader()
   $dt.Load($r)
   $conn.Close()
   return @(,$dt)

  } else {

   $w = $cmd.ExecuteNonQueryAsync()
   return [PSCustomObject]@{result=$w; conn = $conn} }
}


# ---------------------------------------------

# get a list of jobs from your control table, this will run synchronously
$jobList = Async-Sql -connStr $str -sql "select job_id, code from test.control_table where code = '$code'" -GetDataTable

# main loop. You should call your stored procedure here. Each iteration will create a new connection and execute command asynchronously
foreach($id in $jobList.job_id) {

  $command = "EXEC run_job $id, $date"
  $r = Async-Sql -connStr $str -sql $command
  $jobs.Add( $id, $r )

}

# wait for all jobs to complete
while ($False -in $jobs.Values.result.isCompleted) { sleep -Milliseconds 500 }

# print results / close connections. If you see status as RanToCompletion the job is completed successfuly

foreach($j in $jobs.Keys) {
 $res = $jobs[$j].result
[PSCustomObject]@{JobId=$j; isCompleted = $res.isCompleted; Status = $res.Status; result = $res.Result }
$jobs[$j].conn.close()

}

答案 1 :(得分:0)

由于您拥有Powershell V2,因此我将使用PS Jobs添加一个解决方案。将以下代码另存为sqlExec.ps1:

request.args.get('key', None)

然后将此代码用作主脚本:

param($connStr, $sql) 

$conn = New-Object System.Data.SqlClient.SqlConnection $connStr
$cmd = $conn.CreateCommand()
$conn.Open()
$cmd.CommandText = $sql
$r = $cmd.ExecuteNonQuery()
$conn.Close()
return $r 

如果您具有Invoke-Sqlcmd模块,则可以将其用于sql代码执行(而不是创建$ conn,$ cmd等)