none
Выполнение с помощью PowerShell T-SQL файла RRS feed

  • Вопрос

  • Всем привет, Kazun'у - отдельный привет :) !

    Есть такая задача - на  SQL-серверах необходимо выполнить T-SQL-скрипты, но доступ по RDP к ним не всегда есть. Поэтому часто приходится это делать с машин, на которых нет MS SQL Server, соответственно нет и sqlcmd и командлетов PowerShell для MS SQL Server. Ставить на эти машины доп. софт также нельзя. Вот у меня и возникла мысль запускать эти скрипты с помощью PowerShell, который вроде присутствует везде.

    Сделал примерно вот такой скрипт:

    $server = "SQLServer
    $Database = "MyDB"
    $SQLConnection.ConnectionString = "Server=" + $server + ";Database=" + $Database + ";Integrated Security=True"
    $SQLConnection.Open()
    
    $SQLCommandText = Get-Content -Path C:\Temp\TSQLScript.sql
    $SQLCommand = New-Object System.Data.SqlClient.SqlCommand($SQLCommandText, $SQLConnection)
    $SQLCommand.ExecuteScalar()
    $SQLConnection.Close()

    Но вот незадача - Get-Content при считывании файла  рушит всю структуру кода, поэтому вместо T-SQL  в $SQLCommand передается черт знает что, и есс-но это не работает.

    Выход вроде нашел:

    $SQLCommandText = @(Get-Content -Path C:\Temp\TSQLScript.sql)
    $NewSQLCommand = @()
    foreach($SQLString in $SQLCommandText)
    {
    	$NewSQLCommand += $SQLString + "`n"
    }
    $SQLCommand = New-Object System.Data.SqlClient.SqlCommand($NewSQLCommand, $SQLConnection)

    В этом случае структура T-SQL сохраняется, но сам код мне не нравится - несуразно все как это выглядит.

    Подскажите как решить данную задачу более правильно ? 

     


    Andy Mishechkin

    10 декабря 2012 г. 21:23

Ответы

  • Попробовать: [IO.File]::ReadAllText("C:\Temp\TSQLScript.sql")

    IO.File - хорошее дело, вот только без Get-Content все равно не обошлось, поскольку часто в скриптах T-SQL сидят GO, которые не обрабатываются в составе пакета T-SQL.

    Я скрипт полностью переработал - кидаю сюда, может кому-нибудь кроме меня пригодится.

    <#--------------------------------------------------------------------------
    		Script for running T-SQL files in MS SQL Server
    		Andy Mishechkin
    ---------------------------------------------------------------------------#>
    #Script parameters
    param(
    		#Name of MS SQL Server instance
    		[parameter(Mandatory=$true,
    	           HelpMessage="Specify the SQL Server name where will be run a T-SQL code",Position=0)]
    		[String]
    		[ValidateNotNullOrEmpty()]
    		$server = $(throw "sqlserver parameter is required."),
    	
    		#Database name for execution context
    		[parameter(Mandatory=$true,
    	           HelpMessage="Specify the context database name",Position=1)]
    		[String]
    		[ValidateNotNullOrEmpty()]
    		$dbname = $(throw "dbname parameter is required."),
    		
    		#Name of T-SQL file (.sql)
    		[parameter(Mandatory=$true,
    	           HelpMessage="Specify the name of T-SQL file (*.sql) which will be run",Position=2)]
    		[String]
    		[ValidateNotNullOrEmpty()]
    		$file = $(throw "sqlfile parameter is required."),
    		
    		#The GO switch. Must be specified if T-SQL code is contain the GO instructions
    		[parameter(Mandatory=$false,Position=3)]
    		[Switch]
    		[AllowEmptyString()]
    		$go,
    		
    		#MS SQL Server user name
    		[parameter(Mandatory=$false,Position=4)]
    		[String]
    		[AllowEmptyString()]
    		$u,
    		
    		#MS SQL Server password name
    		[parameter(Mandatory=$false,Position=5)]
    		[String]
    		[AllowEmptyString()]
    		$p
    	)
    
    #Connect to MS SQL Server
    try
    {
    	$SQLConnection = New-Object System.Data.SqlClient.SqlConnection
    	#The MS SQL Server user and password is specified
    	if($u -and $p)
    	{
    		$SQLConnection.ConnectionString = "Server=" + $server + ";Database=" + $dbname + ";User ID= " + $u + ";Password=" + $p + ";"
    
    	}
    	#The MS SQL Server user and password is not specified - using the Windows user credentials
    	else
    	{
    		$SQLConnection.ConnectionString = "Server=" + $server + ";Database=" + $dbname + ";Integrated Security=True"
    
    	}
    	$SQLConnection.Open()
    }
    #Error of connection
    catch
    {
    	Write-Host $Error[0]
    	break
    }
    
    #The GO switch is specified - parsing T-SQL code with GO
    if($go)
    {
    	$SQLCommandText = @(Get-Content -Path $file)
    	foreach($SQLString in $SQLCommandText)
    	{
    		if($SQLString -ne "go")
    		{
    			#Preparation of SQL packet
    			$SQLPacket += $SQLString + "`n"
    		}
    		else
    		{
    			#Execution of SQL packet
    			$SQLCommand = New-Object System.Data.SqlClient.SqlCommand($SQLPacket, $SQLConnection)
    			$SQLCommand.ExecuteScalar()
    			$SQLPacket = ""
    		}
    	}
    }
    else
    {
    	#Reading the T-SQL file as a whole packet
    	$SQLCommandText = @([IO.File]::ReadAllText($file))
    	#Execution of SQL packet
    	$SQLCommand = New-Object System.Data.SqlClient.SqlCommand($SQLCommandText, $SQLConnection)
    	$SQLCommand.ExecuteScalar()
    }
    #Disconnection from MS SQL Server
    $SQLConnection.Close()
    
    
    


    Andy Mishechkin

    • Помечено в качестве ответа Andy Mishechkin 12 декабря 2012 г. 0:51
    12 декабря 2012 г. 0:50
  • Попробовать: [IO.File]::ReadAllText("C:\Temp\TSQLScript.sql")

    • Помечено в качестве ответа Andy Mishechkin 11 декабря 2012 г. 18:15
    11 декабря 2012 г. 4:45
    Отвечающий

Все ответы

  • Попробовать: [IO.File]::ReadAllText("C:\Temp\TSQLScript.sql")

    • Помечено в качестве ответа Andy Mishechkin 11 декабря 2012 г. 18:15
    11 декабря 2012 г. 4:45
    Отвечающий
  • Попробовать: [IO.File]::ReadAllText("C:\Temp\TSQLScript.sql")

    IO.File - хорошее дело, вот только без Get-Content все равно не обошлось, поскольку часто в скриптах T-SQL сидят GO, которые не обрабатываются в составе пакета T-SQL.

    Я скрипт полностью переработал - кидаю сюда, может кому-нибудь кроме меня пригодится.

    <#--------------------------------------------------------------------------
    		Script for running T-SQL files in MS SQL Server
    		Andy Mishechkin
    ---------------------------------------------------------------------------#>
    #Script parameters
    param(
    		#Name of MS SQL Server instance
    		[parameter(Mandatory=$true,
    	           HelpMessage="Specify the SQL Server name where will be run a T-SQL code",Position=0)]
    		[String]
    		[ValidateNotNullOrEmpty()]
    		$server = $(throw "sqlserver parameter is required."),
    	
    		#Database name for execution context
    		[parameter(Mandatory=$true,
    	           HelpMessage="Specify the context database name",Position=1)]
    		[String]
    		[ValidateNotNullOrEmpty()]
    		$dbname = $(throw "dbname parameter is required."),
    		
    		#Name of T-SQL file (.sql)
    		[parameter(Mandatory=$true,
    	           HelpMessage="Specify the name of T-SQL file (*.sql) which will be run",Position=2)]
    		[String]
    		[ValidateNotNullOrEmpty()]
    		$file = $(throw "sqlfile parameter is required."),
    		
    		#The GO switch. Must be specified if T-SQL code is contain the GO instructions
    		[parameter(Mandatory=$false,Position=3)]
    		[Switch]
    		[AllowEmptyString()]
    		$go,
    		
    		#MS SQL Server user name
    		[parameter(Mandatory=$false,Position=4)]
    		[String]
    		[AllowEmptyString()]
    		$u,
    		
    		#MS SQL Server password name
    		[parameter(Mandatory=$false,Position=5)]
    		[String]
    		[AllowEmptyString()]
    		$p
    	)
    
    #Connect to MS SQL Server
    try
    {
    	$SQLConnection = New-Object System.Data.SqlClient.SqlConnection
    	#The MS SQL Server user and password is specified
    	if($u -and $p)
    	{
    		$SQLConnection.ConnectionString = "Server=" + $server + ";Database=" + $dbname + ";User ID= " + $u + ";Password=" + $p + ";"
    
    	}
    	#The MS SQL Server user and password is not specified - using the Windows user credentials
    	else
    	{
    		$SQLConnection.ConnectionString = "Server=" + $server + ";Database=" + $dbname + ";Integrated Security=True"
    
    	}
    	$SQLConnection.Open()
    }
    #Error of connection
    catch
    {
    	Write-Host $Error[0]
    	break
    }
    
    #The GO switch is specified - parsing T-SQL code with GO
    if($go)
    {
    	$SQLCommandText = @(Get-Content -Path $file)
    	foreach($SQLString in $SQLCommandText)
    	{
    		if($SQLString -ne "go")
    		{
    			#Preparation of SQL packet
    			$SQLPacket += $SQLString + "`n"
    		}
    		else
    		{
    			#Execution of SQL packet
    			$SQLCommand = New-Object System.Data.SqlClient.SqlCommand($SQLPacket, $SQLConnection)
    			$SQLCommand.ExecuteScalar()
    			$SQLPacket = ""
    		}
    	}
    }
    else
    {
    	#Reading the T-SQL file as a whole packet
    	$SQLCommandText = @([IO.File]::ReadAllText($file))
    	#Execution of SQL packet
    	$SQLCommand = New-Object System.Data.SqlClient.SqlCommand($SQLCommandText, $SQLConnection)
    	$SQLCommand.ExecuteScalar()
    }
    #Disconnection from MS SQL Server
    $SQLConnection.Close()
    
    
    


    Andy Mishechkin

    • Помечено в качестве ответа Andy Mishechkin 12 декабря 2012 г. 0:51
    12 декабря 2012 г. 0:50
  • I suggest you to post it also either in the Gallery section here or in TechNet WiKi as this seems like a very useful thing.

    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog

    12 декабря 2012 г. 0:57
  • I suggest you to post it also either in the Gallery section here or in TechNet WiKi as this seems like a very useful thing.

    Thanks, Naomi!

    It will very nice if my work will be useful for somebody.

    Could you send me some instructions for posting to Gallery or TechNet Wiki.

    Please e-mail me (use e-mail address with clipped _nospam): andy_mishechkin_nospam@hotmail.com


    Andy Mishechkin

    12 декабря 2012 г. 20:40
  • I sent you an e-mail with quick instructions.

    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog

    12 декабря 2012 г. 21:35