[Basic SQL Code] Split Numbers

Olá pessoal,

Este é um artigo rápido onde vou compartilhar um código para fazer o split de uma lista de valores em um formato tabular. A idéia deste trecho de código surgiu em uma de minhas aulas na Impacta, como dúvida de um aluno. Veja abaixo o código na íntegra:

DECLARE
      @COUNT INT,
      @NUMS VARCHAR(100),
      @NUMS_AUX1 VARCHAR(100),
      @NUMS_AUX2 VARCHAR(100),     
      @POS INT,
      @SEPARATOR CHAR(1)
 
— lista de valores    
SET @NUMS = ’10;2;7;55;6;94;8;36;45;88;25′
— separador de cada valor
SET @SEPARATOR = ‘;’
 
SET @COUNT = LEN(@NUMS) –> total de caracteres da lista
SET @POS = 1                  –> posição de retorno da lista
SET @NUMS_AUX1 = ”           –> variável auxiliar 1
SET @NUMS_AUX2 = ”           –> variável auxiliar 2
 
— validação de existência da tabela temporária auxiliar
IF EXISTS(SELECT OBJECT_ID(‘TEMPDB..#NUMS’,’U’))
      DROP TABLE #NUMS
CREATE TABLE #NUMS (NUM INT)
 
— lógica para realizar o split dos números
WHILE @COUNT >= 0
BEGIN
      — variável auxiliar captura primeira posição da sequência
      SELECT @NUMS_AUX1 = SUBSTRING(@NUMS,@POS,1)
     
      — caso o valor capturado seja o separador ou eu tenho lido todos os caracteres,
      — insere o valor na tabela temporária auxiliar
      IF @NUMS_AUX1 = @SEPARATOR OR @COUNT = 0
      BEGIN
            INSERT INTO #NUMS VALUES (@NUMS_AUX2)
            SET @NUMS_AUX2 = ”
      END
      — caso contrário, atribui o valor para a variável auxiliar 2 e continua o loop
      ELSE
            SET @NUMS_AUX2 = @NUMS_AUX2 + ” + @NUMS_AUX1
 
      — decremento e incremento das variáveis @COUNT e @POS, que controla a posição
      — que está sendo capturada na lista de valores
      SET @COUNT -= 1  
      SET @POS += 1
END
 
— Exibe o resultado da lista de valores em formato tabular
SELECT * FROM #NUMS

Bons Estudos!
Erickson

Anúncios

Tutorial – Instalando e configurando VMWare Player

Olá pessoal!

Ontem conversei com uns amigos (Edvaldo – @edvaldocastro02, Vlad – @magalhaesv e Leandro – @sqlleroy ) sobre qual ferramenta cada um utilizava para criar ambientes virtualizados para estudo com o SQL Server.

Há algumas opções para escolha. Virtual PC e Hyper-V (Microsoft), VirtualBox (Sun/Oracle), VMWare Player (VMWare) são as mais conhecidas. Eu particularmente gosto do VMWare Player. É bem prático e rápido para criar e configurar uma nova máquina virtual. Com base nisso, resolvi escrever esse post com um rápido tutorial sobre como instalar o VMWare Player e como configurar uma nova máquina virtual.

NOTA: A versão mais recente do player é a 4.0.1. Não sei por qual razão ainda, não consegui instalar essa versão no Windows 7. Para o tutorial foi utilizada a versão 4.0.0.

UPDATE: Esqueci de colocar o link para download… =P
http://downloads.vmware.com/d/info/desktop_end_user_computing/vmware_player/4_0#product_downloads

Como eu já possuia uma versão anterior instalada, o player pede para proceder com o uninstall da versão anterior antes de instalar a nova.

Desinstalando a versão anterior do VMWare Player

Prossiga com a desinstalação. Ao final, ele vai pedir para você reiniciar a sua máquina.

Após a desinstalação, faça o restart da máquina

Feito o restart da máquina, vamos começar a instalação da nova versão.

Agora ficou fácil, Next, Next, Finish! =D

A instalação vai seguir por alguns minutos e em seguida, para finalizar, mais um restart é solicitado.

Depois deste restart, execute o player. Ele vai aparecer a janela para aceitar os termos de uso, conforme abaixo:

Aceite os termos. Na tela inicial do player, clique na opção para criar uma nova máquina virtual. Veremos a tela a seguir:

Nesta tela podemos escolher entre fazer a instalação do S.O. desta máquina virtual através de uma mídia (CD,DVD), podemos instalar de um arquivo .ISO (opção que eu escolhi) ou podemos deixar para instalar o sistema operacional depois.

Eu escolhi realizar a instalação com um arquivo .ISO. Dica: o VMWare Player consegue reconhecer o sistema operacional que vai ser instalado e realiza uma operação que ele chama de “Easy Install” (Veja a mensagem informativa abaixo da minha escolha). Com isso, fica muito, MUITO mais prático seguir com a instalação como veremos abaixo.

Vamos prosseguir.

Nesta tela devemos inserir a Product Key do S.O. que está sendo instalado. O arquivo .ISO que utilizei possuia algumas versões do Windows, eu escolhi a versão Enterprise para ser instalada. Já inclui um usuário para me logar na máquina futuramente.

NOTA: Não preenchi a Product Key do Windows. Isso não impede que você prossiga com a instalação, mas veremos a mensagem de alerta a seguir:

O Player nos informa que a Product Key não foi informada e podemos prosseguir. No futuro, o Windows terá de ser ativado manualmente. Vamos em frente!

Configure o nome da sua máquina virtual e em qual diretório serão salvos os arquivos dela.

Configure o tamanho do disco da sua máquina virtual. O Player já sugere para você um tamanho mínimo de acordo com o sistema operacional que está sendo instalado. Você tem ainda a opção de salvar os dados em um único arquivo (que é visto como uma unidade dentro da VM) ou ainda fazer o split em vários arquivos. À título de demonstração, deixei um arquivo só mesmo.

É exibido um resumo das configurações que fizemos até o momento. A partir deste ponto já poderíamos finalizar. Caso você queira realizar outras configurações de hardware, clique no botão “Customize Hardware…”.

Você pode configurar a quantidade de memória utilizada pela máquina virtual, quantidade de processadores, adaptadores de rede e outras opções. No momento, não vou fazer nenhuma configuração adicional.

NOTA: Todas estas configurações podem ser realizadas depois que a máquina virtual estiver criada, portanto, não se preocupe por enquanto.

Feche a janela de configurações de hardware e finalize a configuração da máquina virtual. Automaticamente o player vai iniciar a instalação do sistema operacional.

Finaliza a instalação a máquina é iniciada automaticamente.

Bingo! Temos nossa máquina virtual instalada e configurada!

Daqui pra frente é prosseguir com a instalação do SQL Server, fazer suas configurações e se divertir! 😉

Bons estudos!

Análise de um banco de dados corrompido

Olá,

Neste post farei a análise de um banco de dados corrompido. O banco de dados corrompido que irei utilizar foi disponibilizado num grupo de estudos para a certificação MCM no qual estou participando. O grupo foi iniciado pelo MVP Jason Strate ( blog | @StrateSQL ) e quem quiser mais informações pode acessar este post dele: http://www.jasonstrate.com/2011/12/sql-mcm-study-group/.

Vocês poderão baixar o banco de dados corrompido aqui.

Vamos começar a análise então. Antes de mais nada, precisamos deixar nosso banco de dados disponível em nossa instância. A maneira mais simples de fazer isto é anexar (attach) a base, seja pela interface gráfica ou via comando, desta forma:

CREATE DATABASE [CorruptDB1] ON
( FILENAME = N'C:\temp\CorruptDBs\CorruptDB1\DBFiles\CorruptDB1.mdf' ),
( FILENAME = N'C:\temp\CorruptDBs\CorruptDB1\DBFiles\CorruptDB1_log.ldf' )
FOR ATTACH;
GO

Substitua o caminho “C:\temp\CorruptDBs\…” para o local onde você escolher descompactar os arquivos.

Uma vez que o banco de dados estiver anexado, vamos rodar um DBCC CHECKDB para ver qual o estado do nosso banco.

DBCC CHECKDB(CorruptDB1)
WITH ALL_ERRORMSGS, NO_INFOMSGS

Utilizei as opções ALL_ERRORMSGS e NO_INFOMSGS para exibir como resultado somente mensagens de erro e ignorar mensagens informativas. Se desejar mais informações sobre o comando DBCC CHECKDB, clique aqui. O resultado que temos é o seguinte:

Msg 8939, Level 16, State 98, Line 1
Table error: Object ID 99, index ID 0, partition ID 0, alloc unit ID 6488064 (type System allocation data),
page (1:7). Test (IS_OFF (BUF_IOERR, pBUF->bstat)) failed. Values are 12716041 and -4.
CHECKDB found 1 allocation errors and 0 consistency errors in table ‘(Object ID 99)’ (object ID 99).
CHECKDB found 1 allocation errors and 0 consistency errors in database ‘CorruptDB1’.

Há algo errado com nosso banco de dados. E agora, que ação devemos tomar?

O comando CHECKDB possui duas opções chamadas REPAIR_ALLOW_DATA_LOSS e REPAIR_REBUILD. A primeira impressão é “…ótimo, o DBCC CHECKDB vai resolver meu problema de corrupção!”.

A primeira opção “tenta” reparar o problema de corrupção e pode ocasionar perda de dados. Já a segunda opção “tenta” executar reparos que não possibilitem perda de dados. Como não queremos perder nenhum dado da base, vamos executar a segunda opção primeiro. Vou alterar o acesso do banco de dados para SINGLE_USER e vou executar estas opções.

ALTER DATABASE CorruptDB1 SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
GO

DBCC CHECKDB(CorruptDB1, REPAIR_REBUILD)
WITH ALL_ERRORMSGS, NO_INFOMSGS

E temos o seguinte resultado:

Msg 8939, Level 16, State 98, Line 1
Table error: Object ID 99, index ID 0, partition ID 0, alloc unit ID 6488064 (type System allocation data), page (1:7). Test (IS_OFF (BUF_IOERR, pBUF->bstat)) failed. Values are 12584969 and -4.
The repair level on the DBCC statement caused this repair to be bypassed.
CHECKDB found 1 allocation errors and 0 consistency errors in table ‘(Object ID 99)’ (object ID 99).
CHECKDB found 1 allocation errors and 0 consistency errors in database ‘CorruptDB1’.

Hummm… Nada resolvido. Ainda tivemos o erro 8939. Vamos forçar a barra e tentar o reparo com possível perda de dados.

DBCC CHECKDB(CorruptDB1, REPAIR_ALLOW_DATA_LOSS)
WITH ALL_ERRORMSGS, NO_INFOMSGS

E o resultado:

Msg 8939, Level 16, State 98, Line 1
Table error: Object ID 99, index ID 0, partition ID 0, alloc unit ID 6488064 (type System allocation data), page (1:7). Test (IS_OFF (BUF_IOERR, pBUF->bstat)) failed. Values are 12584969 and -4.
The repair level on the DBCC statement caused this repair to be bypassed.
CHECKDB found 1 allocation errors and 0 consistency errors in table ‘(Object ID 99)’ (object ID 99).
CHECKDB found 1 allocation errors and 0 consistency errors in database ‘CorruptDB1’.

Novamente, nada feito. Pelo nível de corrupção do banco de dados, o comando DBCC CHECKDB não consegue reparar este problema. Vamos ter que fazer uma análise um pouco mais profunda e por a mão na massa para resolver o problema.

Nós vamos encontrar a explicação deste erro aqui. Em linhas gerais, ele nos informa que foi realizada uma validação numa determinada página, e esta validação falhou por uma corrupção no cabeçalho (Header) da página. Interessante não?!

Analisando a mensagem completa de erro que nos foi dada, podemos observar que ela nos informa qual é a página que está com problema: “…page (1:7). Test (IS_OFF (BUF_IOERR, pBUF->bstat)) failed. …”. Fica a dica: LEIA TODA A MENSAGEM DE ERRO!!! Achei que isto deveria ficar em destaque pois é muito comum ver as pessoas sem saber o que fazer e a mensagem de erro te dá dicas valiosas sobre o que aconteceu. Nem sempre é assim, mas na maioria das vezes é válido. Vamos dar uma olhada nesta página:

DBCC TRACEON(3604)
GO
DBCC PAGE('CorruptDB1', 1, 7, 3)

Quer saber mais sobre o Trace Flag 3604 e sobre o comando DBCC PAGE, acesse aqui e aqui.
O resultado completo que temos é o seguinte:

DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Msg 8939, Level 16, State 98, Line 1
Table error: Object ID 99, index ID 0, partition ID 0, alloc unit ID 6488064 (type System allocation data), page (1:7). Test (IS_OFF (BUF_IOERR, pBUF->bstat)) failed. Values are 12584969 and -4.PAGE: (1:7)BUFFER:BUF @0x000000008EFA8F40

bpage = 0x000000008E17E000           bhash = 0x0000000000000000           bpageno = (1:7)
bdbid = 17                           breferences = 0                      bcputicks = 0
bsampleCount = 0                     bUse1 = 50557                        bstat = 0xc00809
blog = 0x21212159                    bnext = 0x0000000000000000

PAGE HEADER:

Page @0x000000008E17E000

m_pageId = (1:7)                     m_headerVersion = 0                  m_type = 0
m_typeFlagBits = 0x0                 m_level = 0                          m_flagBits = 0x200
m_objId (AllocUnitId.idObj) = 99     m_indexId (AllocUnitId.idInd) = 0    Metadata: AllocUnitId = 6488064
Metadata: PartitionId = 0            Metadata: IndexId = 0                Metadata: ObjectId = 99
m_prevPage = (0:0)                   m_nextPage = (0:0)                   pminlen = 90
m_slotCnt = 2                        m_freeCnt = 6                        m_freeData = 8182
m_reservedCnt = 0                    m_lsn = (0:0:1)                      m_xactReserved = 0
m_xdesId = (0:0)                     m_ghostRecCnt = 0                    m_tornBits = 105713478

Allocation Status

GAM (1:2) = ALLOCATED                SGAM (1:3) = NOT ALLOCATED           PFS (1:1) = 0x44 ALLOCATED 100_PCT_FULL
DIFF (1:6) = CHANGED                 ML (1:7) = NOT MIN_LOGGED
Msg 2514, Level 16, State 5, Line 1
A DBCC PAGE error has occurred: Invalid page type – dump style 3 not possible.

Obviamente houve erros no resultado. Mas o que chama a atenção são os pontos que destaquei em negrito. Se dermos uma olhada no Internals (um modo “carinhoso” de chamar o livro Microsoft SQL Server 2008 Internals), veremos no capítulo 3, página 147, parágrafo 2 ( :-O Não, eu não decorei isto, fui ver no livro… ^.^ ) as explicações sobre as páginas de alocação de dados, em resumo, assim:

  • Page 0 – File Header
  • Page 1 – PFS Page Free Space
  • Page 2 – GAM Global Allocation Map
  • Page 3 – SGAM Shared Global Allocation Map
  • Page 4 e Page 5 – não são utilizadas
  • Page 6 – DCM Differential Changed Map
  • Page 7 – BCM Bulk Changed Map

Isto nos leva à conclusão de que a página que temos corrompida neste banco de dados é a página BCM, Bulk Changed Map. Não vou entrar neste momento no detalhe das páginas de controle, ficando apenas por dizer que é uma das páginas de controle de alocação de dados do SQL Server.

Ótimo! Agora sabemos o que fazer. Podemos então fazer o restore desta página e tudo resolvido. Será?!
Vamos tentar.

USE MASTER;
GO

RESTORE DATABASE CorruptDB1
   PAGE = '1:7'
FROM DISK = 'C:\temp\CorruptDBs\CorruptDB1\Bak\CorruptDB1.bak'
WITH RECOVERY

Vamos utilizar o comando RESTORE para restaurar somente a nossa página corompida. O resultado que temos é:

Msg 3111, Level 16, State 1, Line 2
Page (1:7) is a control page which cannot be restored in isolation. To repair this page, the entire file must be restored.
Msg 3013, Level 16, State 1, Line 2
RESTORE DATABASE is terminating abnormally.

Ops! O SQL Server não nos permite restaurar isoladamente páginas de controle… E nos informa que para resolução do problema temos de restaurar o arquivo completo.

Solução para o problema e evitar perda de dados. Faça um backup de log (Tail Log Backups) e aplica um restore do banco de dados e depois aplique os logs na sequência, se houver, e por último aplique o último backup de log gerado (tail log). Depois de seguir estes passos, execute novamente o comando DBCC CHECKDB para ter certeza de que seu problema foi resolvido.

Esta foi a solução que encontrei para este problema de corrupção.

Bons estudos e até a próxima!