segunda-feira, 26 de abril de 2010

Novidades T-SQL no SQL Server 2008 - Parte 3

Versão do SQL Server: 2008.

No dois últimos post escrevi sobre duas novidades relacionadas ao uso de variáveis e sobre o comando INSERT, veja nos links abaixo:

Neste terceiro post da série sobre as novidades do T-SQL no SQL Server 2008 veremos GROUPING SET. Até o SQL Server 2005 existiam 3 possibilidades de gerar subtotais em uma consulta, utilizando CUBE, ROLLUP e UNION, como vemos abaixo:

-- SQL 2005 ou inferior
select Cliente, NULL as Ano, sum(Valor) as Valor
from tmpCliente group by Cliente
UNION ALL
select NULL as Cliente, Ano, sum(Valor)
from tmpCliente group by Ano
UNION ALL
select NULL as Cliente, NULL as Ano, sum(Valor)
from tmpCliente
order by 1,2



Como resultado temos uma única consulta contendo:
Em Vermelho – total geral
Em Verde – subtotal por ano
Em azul – subtotal por cliente

No SQL Server 2008, para produzir o mesmo resultado, a consulta fica muito mais simples com GROUPING SET, veja:

select Cliente, Ano, sum(Valor)
from tmpCliente
group by grouping sets((Cliente),(Ano),())
order by 1,2


Até o próximo post,
Landry

segunda-feira, 19 de abril de 2010

Novidades T-SQL no SQL Server 2008 - Parte 2

Versões do SQL Server: 2008.

No último post escrevi sobre duas novidades relacionadas ao uso de variáveis, veja neste link:

Neste post veremos uma opção bem interessante na instrução INSERT, a possibilidade de inclusão de múltiplos valores no mesmo comando INSERT.

Para começar vamos criar uma tabela no banco de dados TempDB utilizando o script abaixo:

use tempdb
go
create table tmpINSERT
(col1 int null, col2 varchar(10) null)
go

Para incluir 4 linhas na tabela tmpINSERT até o SQL Server 2005 utilizávamos o script abaixo:

-- SQL 2005 ou inferior
insert tmpINSERT (col1,col2) values (1,'linha 1')
insert tmpINSERT (col1,col2) values (2,'linha 2')
insert tmpINSERT (col1,col2) values (3,'linha 3')
insert tmpINSERT (col1,col2) values (4,'linha 4')
go

No SQL Server 2008 o script acima continua funcionando, porém temos agora uma opção mais simples veja:

-- SQL 2008
insert tmpINSERT (col1,col2) values
(1,'linha 1'),
(2,'linha 2'),
(3,'linha 3'),
(4,'linha 4')
go

Um único comando INSERT contendo uma lista de valores!

Até o próximo post,
Landry.

sexta-feira, 16 de abril de 2010

Novidades T-SQL no SQL Server 2008 - Parte 1

Versões do SQL Server: 2008.

Estou iniciando uma sequência de posts sobre as novidades do T-SQL no SQL Server 2008. Nesta primeira parte veremos duas novidades:

1) Inicializar uma variável na sua declaração
Até o SQL Server 2005 se utilizava o comando DECLARE para declarar uma variável e depois o comando SET para atribuir um valor (inicializar). Veja no script abaixo:

-- SQL 2005 ou inferior
declare @i int
set @i = 1
select @i

No SQL Server 2008 o script acima continua funcionando, porém agora temos a opção de inicializar a variável junto da sua declaração, veja:

-- SQL 2008
declare @i int = 1
select @i


2) Operadores para incremento
Agora podemos incrementar uma variável utilizando a sintaxe da maioria das linguagens de programação, utilizando +=, veja:

declare @i int = 1
set @i += 1
select @i


Esta sintaxe vale também para outras operações:
+= soma e atribui
-= subtrai e atribui
*= multiplica e atribui
/= divide e atribui
%= Modulo e atribui
&= Bitwise AND e atribui
^= Bitwise XOR e atribui
= Bitwise OR e atribui

Até o próximo post,
Landry

terça-feira, 13 de abril de 2010

Detectar Ausência de Backups em Produção

Versões do SQL Server: 7.0, 2000, 2005 e 2008.

Olá... Vou abordar um assunto simples, porém muito importante para “não abrir a vaga” do DBA: BACKUP.

Você precisa verificar se todos os bancos de dados dos servidores em produção estão com os backups em dia, o que fazer? Colocar simplesmente um alerta no JOB de backup para quando ocorrer uma falha não basta, porque pode existir um banco novo que ainda não tem JOB de backup... Ou então se o JOB de backup foi desabilitado?

Existe um método simples de verificar consultando a tabela backupset no banco de dados de sistema MSDB. Veja a consulta abaixo:

select b.database_name as Banco,b.backup_finish_date as UltimoBackup,
case b.[type]
when 'D' then 'Database'
when 'I' then 'Database Differential'
when 'L' then 'Log'
when 'F' then 'File or Filegroup'
end as TipoBackup -- b.*
from msdb.dbo.backupset b join
(select database_name, max(backup_finish_date) backup_finish_date
from msdb.dbo.backupset group by database_name) u
on b.database_name = u.database_name and b.backup_finish_date = u.backup_finish_date
where b.backup_finish_date < (getdate() - 2) or b.backup_finish_date is null order by b.database_name


A consulta acima retorna uma lista com os bancos de dados onde o último backup feito (não importa o tipo) é anterior a dois dias da data corrente.

Para obter a lista dos bancos de dados sem backup nos últimos 2 dias, basta comparar o resultado da consulta acima com a view sysdatabases, veja:

with BackupFeito as (
select b.database_name as Banco
from msdb.dbo.backupset b join
(select database_name, max(backup_finish_date) backup_finish_date
from msdb.dbo.backupset group by database_name) u
on b.database_name = u.database_name and
b.backup_finish_date = u.backup_finish_date
where b.backup_finish_date < (getdate() - 2) or b.backup_finish_date is null) select name as Banco from sysdatabases s where s.name not in('tempdb','model') and not exists (select * from BackupFeito b where b.Banco = s.name)


Basta rodar esta consulta em cada servidor para obter a listagem dos bancos de dados sem backup nos últimos 2 dias! Você pode automatizar utilizando Linked Server ou PowerShell. Se você estiver no SQL Server 2008 poderá utilizar o recurso de execução de scripts em múltiplas instâncias, veja no post:
http://sqlserver-brasil.blogspot.com/2008/03/executando-scripts-em-mltiplas.html.

Até o próximo post,
Landry

terça-feira, 6 de abril de 2010

Volume de IO por Banco de Dados

Versões do SQL Server: 2005 e 2008.

Após um longo período sem publicar posts estou de volta... Venho publicando vários posts extensos que demandavam muito tempo de pesquisa e escrita, resultando neste longo período de inatividade. Resolvi publicar posts menores, mais simples, abortando temas relacionados ao meu dia a dia como consultor.

Uma instância do SQL Server pode ter vários bancos de dados, seria muito útil para o DBA ter informações estatísticas da atividade de cada banco. Um modo simples de obter estatísticas de IO é o uso da função dinâmica de sistema sys.dm_io_virtual_file_stats. Rode o script abaixo no seu servidor:

with IO_por_Banco as (
select db_name(database_id) as Banco,
cast(sum(num_of_bytes_read + num_of_bytes_written) / 1048576 as decimal(12,2))

as IO_Total_MB,
cast(sum(num_of_bytes_read) / 1048576 as decimal(12,2)) as IO_Leitura_MB,
cast(sum(num_of_bytes_written) / 1048576 as decimal(12,2)) as IO_Escrita_MB
from sys.dm_io_virtual_file_stats(NULL,NULL) as dm
group by database_id)

select row_number() over (order by IO_Total_MB DESC) as Ranking,
Banco, IO_Leitura_MB, IO_Escrita_MB,
IO_Total_MB, cast(IO_Total_MB / sum(IO_Total_MB) over() * 100 as decimal(5,2))

as Percentual
from IO_por_Banco
order by Ranking

O resultado traz o ranking por volume de IO do maior para o menor. O DBA pode utilizar estas informações para planejar a realocação de bancos entre servidores, ou em um projeto de consolidação.

Até o próximo post,
Landry.