我想设置一个新的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”
答案 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等)