كيف يمكنني استدعاء إجراء SQL Server المخزن من PowerShell؟
-
01-07-2019 - |
سؤال
لدي ملف CSV كبير وأريد تنفيذ إجراء مخزن لكل سطر.
ما هي أفضل طريقة لتنفيذ إجراء مخزن من PowerShell؟
المحلول
تم سحب هذه الإجابة من http://www.databasejournal.com/features/mssql/article.php/3683181
يمكن استخدام هذا المثال نفسه لأية استعلامات مخصصة.دعونا ننفذ الإجراء المخزن "sp_helpdb" كما هو موضح أدناه.
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=HOME\SQLEXPRESS;Database=master;Integrated Security=True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "sp_helpdb"
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
$DataSet.Tables[0]
نصائح أخرى
إليك الوظيفة التي أستخدمها (منقحة قليلاً).يسمح بمعلمات الإدخال والإخراج.لدي فقط أنواع فريدة من نوعها و varchar تم تنفيذها، ولكن من السهل إضافة أي أنواع أخرى.إذا كنت تستخدم الإجراءات المخزنة ذات المعلمات (أو مجرد SQL ذات معلمات... فمن السهل تكييف هذا الرمز مع ذلك)، وهذا سيجعل حياتك أسهل كثيرًا.
لاستدعاء الوظيفة، تحتاج إلى اتصال بخادم SQL (على سبيل المثال $conn)،
$res=exec-storedprocedure -storedProcName 'stp_myProc' -parameters @{Param1="Hello";Param2=50} -outparams @{ID="uniqueidentifier"} $conn
استرداد إخراج proc من الكائن الذي تم إرجاعه
$res.data #dataset تحتوي على جداول البيانات التي تم إرجاعها بواسطة التحديدات
$res.outputparams.ID # معرف معلمة الإخراج (معرف فريد)
الوظيفة:
function exec-storedprocedure($storedProcName,
[hashtable] $parameters=@{},
[hashtable] $outparams=@{},
$conn,[switch]$help){
function put-outputparameters($cmd, $outparams){
foreach($outp in $outparams.Keys){
$cmd.Parameters.Add("@$outp", (get-paramtype $outparams[$outp])).Direction=[System.Data.ParameterDirection]::Output
}
}
function get-outputparameters($cmd,$outparams){
foreach($p in $cmd.Parameters){
if ($p.Direction -eq [System.Data.ParameterDirection]::Output){
$outparams[$p.ParameterName.Replace("@","")]=$p.Value
}
}
}
function get-paramtype($typename,[switch]$help){
switch ($typename){
'uniqueidentifier' {[System.Data.SqlDbType]::UniqueIdentifier}
'int' {[System.Data.SqlDbType]::Int}
'xml' {[System.Data.SqlDbType]::Xml}
'nvarchar' {[System.Data.SqlDbType]::NVarchar}
default {[System.Data.SqlDbType]::Varchar}
}
}
if ($help){
$msg = @"
Execute a sql statement. Parameters are allowed.
Input parameters should be a dictionary of parameter names and values.
Output parameters should be a dictionary of parameter names and types.
Return value will usually be a list of datarows.
Usage: exec-query sql [inputparameters] [outputparameters] [conn] [-help]
"@
Write-Host $msg
return
}
$close=($conn.State -eq [System.Data.ConnectionState]'Closed')
if ($close) {
$conn.Open()
}
$cmd=new-object system.Data.SqlClient.SqlCommand($sql,$conn)
$cmd.CommandType=[System.Data.CommandType]'StoredProcedure'
$cmd.CommandText=$storedProcName
foreach($p in $parameters.Keys){
$cmd.Parameters.AddWithValue("@$p",[string]$parameters[$p]).Direction=
[System.Data.ParameterDirection]::Input
}
put-outputparameters $cmd $outparams
$ds=New-Object system.Data.DataSet
$da=New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
[Void]$da.fill($ds)
if ($close) {
$conn.Close()
}
get-outputparameters $cmd $outparams
return @{data=$ds;outputparams=$outparams}
}
إليك وظيفة أستخدمها لتنفيذ أوامر SQL.عليك فقط تغيير $sqlCommand.CommandText إلى اسم sproc الخاص بك و$SqlCommand.CommandType إلى CommandType.StoredProcedure.
function execute-Sql{
param($server, $db, $sql )
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = 'server=' + $server + ';integrated security=TRUE;database=' + $db
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.CommandTimeout = 120
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText= $sql
$text = $sql.Substring(0, 50)
Write-Progress -Activity "Executing SQL" -Status "Executing SQL => $text..."
Write-Host "Executing SQL => $text..."
$result = $sqlCommand.ExecuteNonQuery()
$sqlConnection.Close()
}
استخدم sqlcmd بدلاً من osql إذا كانت قاعدة بيانات 2005
فكر في استدعاء osql.exe (أداة سطر الأوامر لـ SQL Server) وتمرير ملف نصي مكتوب لكل سطر مع استدعاء الإجراء المخزن كمعلمة.
يوفر SQL Server بعض التجميعات التي يمكن استخدامها باسم SMO والتي تتمتع بتكامل سلس مع PowerShell.وهنا مقال عن ذلك.
http://www.databasejournal.com/features/mssql/article.php/3696731
هناك طرق API لتنفيذ الإجراءات المخزنة التي أعتقد أنها تستحق التحقيق فيها.هنا مثال لبدء التشغيل:
http://www.eggheadcafe.com/software/aspnet/29974894/smo-running-a-stored-pro.aspx
أنا أشمل invoke-sqlcmd2.ps1
و write-datatable.ps1
من http://blogs.technet.com/b/heyscriptingguy/archive/2010/11/01/use-powershell-to-collect-server-data-and-write-to-sql.aspx.تأخذ استدعاءات تشغيل أوامر SQL النموذج: Invoke-sqlcmd2 -ServerInstance "<sql-server>" -Database <DB> -Query "truncate table <table>"
يبدو مثال لكتابة محتويات متغيرات DataTable إلى جدول SQL كما يلي: $logs = (get-item SQLSERVER:\sql\<server_path>).ReadErrorLog()
Write-DataTable -ServerInstance "<sql-server>" -Database "<DB>" -TableName "<table>" -Data $logs
أجد هذه مفيدة عند تنفيذ البرامج النصية PowerShell المتعلقة بقاعدة بيانات SQL Server حيث أن البرامج النصية الناتجة نظيفة وقابلة للقراءة.