Criando um arquivo de trace com PowerShell via SMO

Não muito diferente do artigo original com .NET, com PowerShell também conseguimos criar um script simples para gerar um arquivo de trace de uma determinada instancia do SQL Server.

# Referências
[void][system.reflection.assembly]::loadfrom("C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.ConnectionInfo.dll")
[void][system.reflection.assembly]::loadfrom("C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.ConnectionInfoExtended.dll")

function Get-Date2(){
    [System.DateTime]::UtcNow
}

$template = "C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Profiler\Templates\Microsoft SQL Server\100\Tuning.tdf"

$date = Get-Date

$file = "C:\Temp\Trace$($date.Year)-$($date.Month)-$($date.Day) $($date.Hour)-$($date.Minute)-$($date.Second).trc"

$conn = new-object Microsoft.SqlServer.Management.Common.SqlConnectionInfo

$conn.ServerName = "Dalilah"

$traceReader = new-object Microsoft.SqlServer.Management.Trace.TraceServer

$traceReader.InitializeAsReader($conn, $template)

$traceFile = new-object Microsoft.SqlServer.Management.Trace.TraceFile

$traceFile.InitializeAsWriter($traceReader, $file)

$timeout = (Get-Date2).AddSeconds(30)

while ($traceFile.Write() -eq $TRUE -and $timeout -gt (Get-Date2)) { }

$traceFile.Close()

$traceReader.Close()

E o resultado:

Arquivo de trace gerado com PowerShell via SMO

Capturando consultas executadas no SQL Server (Trace) com PowerShell via SMO

Diferente do artigo original “Capturando consultas executadas no SQL Server (Trace) com .NET via SMO”, não consegui utilizar no PowerShell Threads ou Jobs (Jobs do PowerShell e não do SQL Server) para criar uma estrutura de timeout simples para este exemplo.

Assim optei por limitar a quantidade de linhas geradas pelo Trace (no caso 10 linhas), ao invés de criar um timeout com Get-Date (que vou demonstrar no exemplo da próxima semana).

Sem mais, segue o script para trabalhar com Trace no SQL Server com PowerShell:

# Referências
[void][system.reflection.assembly]::loadfrom("C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.ConnectionInfo.dll")
[void][system.reflection.assembly]::loadfrom("C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.ConnectionInfoExtended.dll")

$template = "C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Profiler\Templates\Microsoft SQL Server\100\Standard.tdf"

$conn = new-object Microsoft.SqlServer.Management.Common.SqlConnectionInfo

$conn.ServerName = ".\SQLEXPRESS"

#Criando o objeto TraceServer
$traceReader = new-object Microsoft.SqlServer.Management.Trace.TraceServer

#Iniciando a leitura do trace a partir do template Standard do SQL Server Profiler
$traceReader.InitializeAsReader($conn, $template)

$line = 0

#Lê até 10 comandos executados (enquanto $line < 10)
while ($traceReader.Read() -eq $TRUE -and $line -lt 10)
{
    $name = $traceReader.GetValue($traceReader.GetOrdinal("EventClass"));

    if ($name.Equals("SQL:BatchCompleted") -or $name.Equals("RPC:Completed")) {

        $spid = $traceReader.GetValue($traceReader.GetOrdinal("SPID"))

        $query = $traceReader.GetValue($traceReader.GetOrdinal("TextData"))

        $duration = $traceReader.GetValue($traceReader.GetOrdinal("Duration"))

        "-- SPID: $spid | Duration: $duration"

        "`n"

        Write-Host $query

        "`n `n"

        $line++
    }
}

#Fechando o trace de leitura
$traceReader.Close()

Criando Constraints e Índices no SQL Server com PowerShell

Para continuar com o prometido no primeiro artigo desta série de artigos sobre SMO, teremos a versão em PowerShell do artigo desta semana, que ao meu ver não ficou tão simples quanto o mesmo código escrito em .NET, mas permite ver como PowerShell pode ser mais simples que .NET em alguns momentos, e em outros nem tanto.

Continuar lendo

Criando e manipulando Tabelas e Colunas no SQL Server com PowerShell

Partindo da mesma ideia do artigo anterior, apresento agora a utilização do SMO em um script PowerShell com objetivo de criar e manipular uma tabela no SQL Server:

# Referências
[void][system.reflection.assembly]::loadfrom("C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.Smo.dll")

# Objetos
$server = new-object Microsoft.SqlServer.Management.Smo.Server(".\SQLEXPRESS")

# CREATE DATABASE [Estoque]
$database = new-object Microsoft.SqlServer.Management.Smo.Database($server, "Estoque")

$database.Create()

# Tipos a serem utilizados
$constraint_pk = [Microsoft.SqlServer.Management.Smo.IndexKeyType]::DriPrimaryKey
$type_int = [Microsoft.SqlServer.Management.Smo.DataType]::Int
$type_money =[Microsoft.SqlServer.Management.Smo.DataType]::Money
$type_varchar250 = [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(250)
$type_decimal5_2 = [Microsoft.SqlServer.Management.Smo.DataType]::Decimal(2, 5)
$type_datetime = [Microsoft.SqlServer.Management.Smo.DataType]::DateTime

# CREATE TABLE [dbo].[Produto]
$table = new-object Microsoft.SqlServer.Management.Smo.Table($database, "Produto", "dbo")

#   [Id] [int] IDENTITY(1,1) NOT NULL
$col = new-object Microsoft.SqlServer.Management.Smo.Column($table, "Id", $type_int)
$col.Nullable = $FALSE
$col.Identity = $TRUE
$table.Columns.Add($col)

#   [Nome] [varchar](250) NOT NULL
$col = new-object Microsoft.SqlServer.Management.Smo.Column($table, "Nome", $type_varchar250)
$col.Nullable = $FALSE
$table.Columns.Add($col)

#   [Quantidade] [int] NOT NULL
$col = new-object Microsoft.SqlServer.Management.Smo.Column($table, "Quantidade", $type_int)
$col.Nullable = $FALSE
$table.Columns.Add($col)

#   [Valor] [money] NOT NULL
$col = new-object Microsoft.SqlServer.Management.Smo.Column($table, "Valor", $type_money)
$col.Nullable = $FALSE
$table.Columns.Add($col)

#   [Peso] [decimal](5, 2) NOT NULL
$col = new-object Microsoft.SqlServer.Management.Smo.Column($table, "Peso", $type_decimal5_2)
$col.Nullable = $FALSE
$table.Columns.Add($col)

#   [Frete] [money] NULL
$col = new-object Microsoft.SqlServer.Management.Smo.Column($table, "Frete", $type_money)
$col.Nullable = $TRUE
$table.Columns.Add($col)

$table.Create()

# ALTER TABLE [dbo].[Produto]
#   DROP COLUMN [Frete]

$table.Columns["Frete"].Drop()

# ALTER TABLE [dbo].[Produto]
#   ADD CONSTRAINT [PK_Produto] PRIMARY KEY ([Id])
$pk = new-object Microsoft.SqlServer.Management.Smo.Index($table, "PK_Produto")
$pk.IndexKeyType = $constraint_pk

$col = new-object Microsoft.SqlServer.Management.Smo.IndexedColumn($pk, "Id")
$pk.IndexedColumns.Add($col)

$pk.Create()

# Criando colunas em tabelas já existentes:

## Forma #1
# ALTER TABLE [dbo].[Produto]
#   ADD [CategoriaId] [int] NOT NULL
$col = new-object Microsoft.SqlServer.Management.Smo.Column($table, "CategoriaId", $type_int)
$col.Nullable = $FALSE
$table.Columns.Add($col)
$table.Alter()

## Forma #2
# ALTER TABLE [dbo].[Produto]
#   ADD [DataCadastro] [datetime] NOT NULL
$col = new-object Microsoft.SqlServer.Management.Smo.Column($table, "DataCadastro", $type_datetime)
$col.Nullable = $FALSE
$col.Create()

# DROP TABLE [dbo].[Produto]
$table.Drop()

# DROP DATABASE [dbo].[Estoque]
$database.Drop()

Gerando scripts do banco de dados por PowerShell – Passo 2

Partindo da mesma ideia de utilizar o objeto Scripter do SMO para gerar o scripts do SQL Server por .NET, agora veremos como fazer o mesmo procedimento com PowerShell:

# Referências
[void][system.reflection.assembly]::loadfrom("C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.Smo.dll")
[void][system.reflection.assembly]::loadfrom("C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.Management.Sdk.Sfc.dll")

# Objetos
$srv = new-object Microsoft.SqlServer.Management.Smo.Server(".\SQLEXPRESS")

$db = $srv.Databases["DemoAspNet"]

# Gerando o script do banco de dados
$script = $db.Script()

$script += "`nUSE [DemoAspNet]`n"

# Relacionando as URNs dos objetos que serão "scriptados"

[Microsoft.SqlServer.Management.Sdk.Sfc.Urn[]]$roles =
    $db.Roles | Where { $_.IsFixedRole -eq $FALSE } | % { $_.Urn }

[Microsoft.SqlServer.Management.Sdk.Sfc.Urn[]]$schemas =
    $db.Schemas | Where { $_.IsSystemObject -eq $FALSE } | % { $_.Urn }

[Microsoft.SqlServer.Management.Sdk.Sfc.Urn[]]$tables =
    $db.Tables | Where { $_.IsSystemObject -eq $FALSE } | % { $_.Urn }

[Microsoft.SqlServer.Management.Sdk.Sfc.Urn[]]$views =
    $db.Views | Where { $_.IsSystemObject -eq $FALSE } | % { $_.Urn }

[Microsoft.SqlServer.Management.Sdk.Sfc.Urn[]]$procs =
    $db.StoredProcedures | Where { $_.IsSystemObject -eq $FALSE } | % { $_.Urn }

$urn = new-object Microsoft.SqlServer.Management.Smo.UrnCollection

$urn.AddRange($roles)
$urn.AddRange($schemas)
$urn.AddRange($tables)
$urn.AddRange($views)
$urn.AddRange($procs)

$scr = new-object Microsoft.SqlServer.Management.Smo.Scripter
$scr.Server = $srv
$scr.Options.DriAll = $TRUE

# Gerando o script dos objetos pelo Scripter
$script += $scr.Script($urn)

# Salvando o script gerado em um arquivo
$go = "`nGO`n"

$script | % { $_ + $go} | Out-File "C:\Temp\DemoAspNet.sql"

Forma resumida para ser executado dentro do próprio contexto do SQL Server (Jobs, PowerShell do SQL Server ou sqlps.exe):

# Sem referências

# Objetos
sl SQLSERVER:\SQL\LOCALHOST\SQLEXPRESS

$srv = get-item .

sl Databases\DemoAspNet

$db = get-item .

# Gerando o script do banco de dados
$script = $db.Script()

$script += "`nUSE [DemoAspNet]`n"

# Relacionando as URNs dos objetos que serão "scriptados"

[Microsoft.SqlServer.Management.Sdk.Sfc.Urn[]]$roles =
    dir Roles | Where { $_.IsFixedRole -eq $FALSE } | % { $_.Urn }

[Microsoft.SqlServer.Management.Sdk.Sfc.Urn[]]$schemas =
    dir Schemas | Where { $_.IsSystemObject -eq $FALSE } | % { $_.Urn }

[Microsoft.SqlServer.Management.Sdk.Sfc.Urn[]]$tables =
    dir Tables | Where { $_.IsSystemObject -eq $FALSE } | % { $_.Urn }

[Microsoft.SqlServer.Management.Sdk.Sfc.Urn[]]$views =
    dir Views | Where { $_.IsSystemObject -eq $FALSE } | % { $_.Urn }

[Microsoft.SqlServer.Management.Sdk.Sfc.Urn[]]$procs =
    dir StoredProcedures | Where { $_.IsSystemObject -eq $FALSE } | % { $_.Urn }

$urn = new-object Microsoft.SqlServer.Management.Smo.UrnCollection

$urn.AddRange($roles)
$urn.AddRange($schemas)
$urn.AddRange($tables)
$urn.AddRange($views)
$urn.AddRange($procs)

$scr = new-object Microsoft.SqlServer.Management.Smo.Scripter
$scr.Server = $srv
$scr.Options.DriAll = $TRUE

# Gerando o script dos objetos pelo Scripter
$script += $scr.Script($urn)

# Salvando o script gerado em um arquivo
$go = "`nGO`n"

$script | % { $_ + $go} | Out-File "C:\Temp\DemoAspNet.sql"

Gerando scripts do banco de dados por PowerShell – Passo 1

Tento já explicado como utilizar o SMO para gerar o scripts do SQL Server por .NET, agora teremos a alternativa com PowerShell:

# Referências
[void][system.reflection.assembly]::loadfrom("C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.Smo.dll")

# Objetos
$srv = new-object Microsoft.SqlServer.Management.Smo.Server(".\SQLEXPRESS")

$db = $srv.Databases["DemoAspNet"]

# 1. Gerando o Script do banco de dados
$db.Script() | Out-File "C:\Temp\DemoAspNet.sql"

# 2. Gerando o Script das tabelas do banco de dados
$db.Tables | % { $_.Script() } | Out-File "C:\Temp\DemoAspNet_Tables.sql"

# 3. Script com o GO entre as linhas (Forma 1)
$go = "`nGO`n"
$db.Tables | % { $_.Script() | % { $_ + $go} } | Out-File "C:\Temp\DemoAspNet_Tables.sql"

# 4. Script com o GO entre as linhas (Forma 2)
$go = "
GO
"
$db.Tables | % { $_.Script() | % { $_ + $go} } | Out-File "C:\Temp\DemoAspNet_Tables.sql"

# 5. Gerando o DROP das tabelas
$options = new-object Microsoft.SqlServer.Management.Smo.ScriptingOptions
$options.ScriptDrops = $TRUE

$go = "`nGO`n"
$db.Tables | % { $_.Script($options) | % { $_ + $go} } | Out-File "C:\Temp\DemoAspNet_TableDrop.sql"

# 6. Gerando o script das tabelas com as Primary Keys
$options = new-object Microsoft.SqlServer.Management.Smo.ScriptingOptions
$options.DriPrimaryKey = $TRUE

$go = "`nGO`n"
$db.Tables | % { $_.Script($options) | % { $_ + $go} } | Out-File "C:\Temp\DemoAspNet_TableKey.sql"

# 7. Gerando o script das tabelas com as Keys e Constraints, sem Collation
$options = new-object Microsoft.SqlServer.Management.Smo.ScriptingOptions
$options.DriAll = $TRUE
$options.NoCollation = $TRUE

$go = "`nGO`n"
$db.Tables | % { $_.Script($options) | % { $_ + $go} } | Out-File "C:\Temp\DemoAspNet_TableAll.sql"

Forma resumida para este script se executado dentro do próprio contexto do SQL Server (Jobs, PowerShell do SQL Server ou sqlps.exe):

# Sem referências

# Objetos
sl SQLSERVER:\SQL\LOCALHOST\SQLEXPRESS\Databases\DemoAspNet

$db = get-item .

# 1. Gerando o Script do banco de dados
$db.Script() | Out-File "C:\Temp\DemoAspNet.sql"

# 2. Gerando o Script das tabelas do banco de dados
dir Tables | % { $_.Script() } | Out-File "C:\Temp\DemoAspNet_Tables.sql"

# 3. Script com o GO entre as linhas (Forma 1)
$go = "`nGO`n"
dir Tables | % { $_.Script() | % { $_ + $go} } | Out-File "C:\Temp\DemoAspNet_Tables.sql"

# 4. Script com o GO entre as linhas (Forma 2)
$go = "
GO
"
$db.Tables | % { $_.Script() | % { $_ + $go} } | Out-File "C:\Temp\DemoAspNet_Tables.sql"

# 5. Gerando o DROP das tabelas
$options = new-object Microsoft.SqlServer.Management.Smo.ScriptingOptions
$options.ScriptDrops = $TRUE

$go = "`nGO`n"
dir Tables | % { $_.Script($options) | % { $_ + $go} } | Out-File "C:\Temp\DemoAspNet_TableDrop.sql"

# 6. Gerando o script das tabelas com as Primary Keys
$options = new-object Microsoft.SqlServer.Management.Smo.ScriptingOptions
$options.DriPrimaryKey = $TRUE

$go = "`nGO`n"
dir Tables | % { $_.Script($options) | % { $_ + $go} } | Out-File "C:\Temp\DemoAspNet_TableKey.sql"

# 7. Gerando o script das tabelas com as Keys e Constraints, sem Collation
$options = new-object Microsoft.SqlServer.Management.Smo.ScriptingOptions
$options.DriAll = $TRUE
$options.NoCollation = $TRUE

$go = "`nGO`n"
dir Tables | % { $_.Script($options) | % { $_ + $go} } | Out-File "C:\Temp\DemoAspNet_TableAll.sql"

Artigo relacionado:

PowerShell no SQL Server – Step 1

Gerando backups do SQL Server por PowerShell

No primeiro artigo desta semana vimos como gerar backups do SQL Server por .NET, agora veremos alternativas mais simples para tal, com o PowerShell.

Para o nosso primeiro script de Backup com PowerShell, precisaremos referenciar os assemblies do SMO, e criar um código semelhante ao que vimos com .NET:

# Referências
[void][system.reflection.assembly]::loadfrom("C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.Smo.dll")
[void][system.reflection.assembly]::loadfrom("C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.SmoExtended.dll")

# Objetos
$srv = new-object Microsoft.SqlServer.Management.Smo.Server(".\SQLEXPRESS")

$bk = new-object Microsoft.SqlServer.Management.Smo.Backup

# Definindo de qual banco de dados será executado o backup
$bk.Database = "BASE1"

# Definindo onde será salvo o backup
$bk.Devices.AddDevice("C:\TEMP\BASE1_PowerShell.bak", [Microsoft.SqlServer.Management.Smo.DeviceType]::File)

# Executando o backup
$bk.SqlBackup($srv)

Mas quando no contexto do PowerShell do SQL Server (scripts executados em Jobs ou diretamente pelo PowerShell presente no SQL Server Management Studio ou SQLPS.exe), teremos algumas facilidades, como não precisar referenciar os assemblies do SMO e utilizar de “atalhos” para instanciar as variáveis do SQL Server (ex.: Smo.Server):

# Sem referências

# Objetos
$srv = get-item SQLSERVER:\SQL\LOCALHOST\SQLEXPRESS

$bk = new-object Microsoft.SqlServer.Management.Smo.Backup

# Definindo de qual banco de dados será executado o backup
$bk.Database = "BASE1"

# Definindo onde será salvo o backup
$bk.Devices.AddDevice("C:\TEMP\BASE1_PowerShell.bak", [Microsoft.SqlServer.Management.Smo.DeviceType]::File)

# Executando o backup
$bk.SqlBackup($srv)

Referências:

How To Load .NET Assemblies In A PowerShell Session

PowerShell – Especial de Natal

Boa noite pessoas,

Seguindo tradição do blog, pelo terceiro Natal consecutivo, estava planejando algo bem diferente dos anos anteriores, e em conversas com o @WilliamPietro, tivemos a ideia de criar um script de PowerShell especial para esta data.

Abaixo o script:

$a = (Get-Host).UI.RawUI
$a.WindowTitle = "PowerShell - Especial de Natal"
$b = $a.WindowSize
$b.Width = 18
$b.Height = 12
$a.WindowSize = $b

$c = "        .`n       .#.`n      .###.`n     .#%##%.`n    .%##%###.`n   .##%###%##.`n  .#%###%##%##.`n        #`n        #`n"

1..300 | % {
	$a.BackgroundColor = "darkgreen"
	$a.ForegroundColor = "white"
	cls
	Write-Host $c
	Write-Host "    HO HO HO"
	Wait-Event -timeout 1
	$a.BackgroundColor = "red"
	$a.ForegroundColor = "white"
	cls
	Write-Host $c
	Write-Host "   Feliz Natal"
	Wait-Event -timeout 1
}

Resultado, durante aproximadamente 10 minutos a tela do PowerShell exibirá de forma alternada as seguintes mensagens:

Boas festas, e que tenhamos um ótimo 2012!

Artigos relacionados:

Artigo de Natal de 2009

Artigo de Natal de 2010

PowerShell no SQL Server – Step 3: Jobs

Bom dia pessoas!

Já pensou em automatizar algum processo com PowerShell no SQL Server, mas não sabia como fazê-lo? Então vamos ao SQL Server Agent, um serviço do SQL Server que é utilizado basicamente para agendar rotinas, que além de rotinas T-SQL, também oferece suporte ao PowerShell.

Com o serviço do SQL Server Agent iniciado, configuraremos um novo Job:

Nesta tela, definimos nome e descrição do Job (nomes bem intuitivos, por favor):

Prosseguimos para aba Steps, onde os passos a serem executados por seu Job serão configurados:

No caso, precisaremos de um novo Step do tipo PowerShell:

Na caixa de texto “Command”, coloque os comandos do PowerShell que serão executado, ou importe com o botão “Open…” um arquivo com estes comando.

Importante, os scripts executado pelo SQL Server Agent iniciam numa pasta do servidor (ex.: C:\), assim é altamente remendado informar com o comando “Set-Location” (“cd” ou “sl” também servem), o “path” onde serão executados seus comandos.

cd SQLSERVER:\SQL\<<Nome do Servidor>>\<<Nome da Instância>>\Databases
dir |out-file 'c:\temp\dir.txt'

Concluída a criação do Job, vamos executá-lo:

Acompanhando se tudo executou corretamente:

E o resultado:

Caso deseje agendar seu Job, vá à aba Schedule e adicione um novo agendamento:

Por exemplo, para executar este Job uma vez a cada hora:

Por fim, será possível acompanhar as execuções de seu Job com o “View History”:

Onde haverá detalhamento de todos os passos executados:

Terminado o terceiro passo de como utilizar o PowerShell no SQL Server!

Dúvidas e sugestões? Não se esqueçam de comentar!

PowerShell no SQL Server – Step 2

Uma pergunta comum para quem quer utilizar o tradicional prompt do PowerShell (PowerShell.exe) ou Windows PowerShell ISE (PowerShell_ISE.exe) para codificar seus scripts, é “como executar os mesmos comandos e navegar pelas instâncias igual ao PowerShell que acompanham o SQL Server (SQLPS.exe)”?

Se você possui o SQL Server Management Studio (SSMS) será simples, abra o prompt do PowerShell e execute o seguinte comando, para ter a relação de “Snap-in”s disponíveis:

Get-PSSnapin -registered | Where {$_.Name -like 'SQL*'} | Select Name

No meu cenário, adicionarei os “Snap-in”s do SQL Server 2008 (versão ‘100’ ou melhor 10.0), com os seguintes comandos:

Add-PSSnapin SqlServerCmdletSnapin100
Add-PSSnapin SqlServerProviderSnapin100

Adicionados os “Snap-in”s , com o comando Get-PSDrive será possível encontrar um novo drive para se ‘navegar’ com o PowerShell:

Agora vamos à nossa instância do SQL Server, com seguinte comando:

cd SQLSERVER:\SQL\<<NomeDoServidor>>\<<NomeDaInstância>>

Agora estamos no mesmo caminho do primeiro artigo.

Referências:
http://blogs.msdn.com/b/mwories/archive/2008/06/14/sql2008_5f00_powershell.aspx