كيف يمكنني استدعاء إجراء SQL Server المخزن من PowerShell؟

StackOverflow https://stackoverflow.com/questions/83410

  •  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 حيث أن البرامج النصية الناتجة نظيفة وقابلة للقراءة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top