Meu novo trabalho como DBA no IBPT

E ai pessoas!

Na semana passada, eu comecei a trabalhar como Administrador de Banco de Dados no IBPT (Instituto Brasileiro de Planejamento Tributário). Esta será uma ótima oportunidade para eu voltar a trabalhar diretamente com SQL Server, e rever o que ao longo destes cinco anos aprendi sobre Data Mining e Data Warehouse.

Isso não quer dizer que eu saí da EuroIT Tecnologia, mas vou manter esta atuação nas duas empresas em períodos diferentes, principalmente pelo aprendizado que me é permitido por estas empresas, que possuem cenários bem distintos, além das atuações que desenvolvo em paralelo, como blogger, consultor de TI, professor e aluno do Mestrado em Administração da PUCPR.

A partir de agora, também vou informar no blog os lançamentos dos projetos que tenho participado na EuroIT e no IBPT, com a expectativa de receber feedbacks de vocês que leem o blog, além de fazer conhecida minha atuação nestes projetos e as pessoas trabalham comigo, assim como fazer conhecidos os projetos propriamente ditos.

Anúncios

O Profissional de Banco de Dados

A área de banco de dados é um ramo da tecnologia de informação muito pouco explorado em comparação da necessidade das empresas de soluções.

Considero o profissional de banco de dados um especialista em infra-estrutura, em desenvolvimento e/ou em negócios, que possui capacidade de prover serviços de qualidade na área de banco de dados. Desta forma o fato dele ter conhecimento de banco de dados somente é um diferencial competitivo entre os vários outros profissionais da área de tecnologia da informação.

Existem tentativas de categorizar os profissionais de banco de dados, basicamente divididos nas categorias de Administrador de Banco de dados (Database Administrador), Desenvolvedor de Banco de dados (Database Developer) e Profissional em Business Intelligence, mas todas são somente formas das empresas conseguirem entender qual “DBA” precisam contratar.

O profissional em banco de dados não pode ser somente DBA ou desenvolvedor ou somente o cara do BI. Na verdade ele precisa ser um profissional “Google” (“Wikipédia” ou “Yahoo” ou “Bing” se preferir), pois as organizações estão sedentas de profissionais capacitados e elas não importam muito com qual o nome do cargo dele, mas sim “como ele pode me auxiliar na minha estratégia?”. Este auxílio pode ser uma solução maravilhosa com a qual a empresa pode ganhar (ou não perder) dinheiro ou o simples fato de ter este profissional tudo na empresa estará funcionando perfeitamente.

E respondendo a pergunta “Qual é a minha visão do mercado para o DBA hoje em dia?” que recebi do Anderson, existem muitas oportunidades de trabalho na área de TI, principalmente para profissionais de banco de dados, só que para preencher estas vagas é necessário provar sua aptidão para ocupá-la, então se qualifique e aproveite sempre a oportunidade de aprender mais! Pessoalmente gosto muito deste ramo e vejo nele muitas oportunidades de crescimento.

Como eu disse “conhecer de banco de dados somente é um diferencial competitivo”, logo é possível aumentar o impacto deste diferencial, com trabalho, estudos, treinamentos e dedicação, mas não deve se esquecer de temperar com um pouco de “Google” e aprender também sobre o que esta além do banco de dados.

Obrigado pelas críticas e sugestões que tenho recebido!

 

Artigos relevantes:

http://imasters.uol.com.br/artigo/10797/bancodedados/quer_um_emprego_como_dba/

http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!299.entry

http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!136.entry

http://imasters.uol.com.br/artigo/13518/oracle/que_tipo_de_dba_e_voce/ 
(Profissional Google para eles quer dizer outra coisa…rsss)

http://guiarh.com.br/y68.htm

http://guiarh.com.br/pp54.htm

Consultas desordenadas e aleatórias

A idéia inicial deste post é trabalhar com ordem desordenada! Não se surpreenda, nem diga que estou louco, mas o que estou tratando é algo comum do dia-a-dia.

Vamos à situação, imagina que você possui uma tabela de categoria de produtos, com os seguintes dados:

Código Nome
1 Sapatos
2 Cintos
3 Chapeis
4 Calçar
5 Casacos
6 Camisas
7 Meias
8 Pijamas
9 Outros

 

Mas agora o cliente deseja que sempre a categoria “Outros” apareça em primeiro em um determinado relatório. Ok, você em minutos vai à query:

SELECT Código, Nome FROM Categoria

E altera para:

SELECT Código, Nome FROM Categoria ORDER BY Código DESC

Resultado disso, agora o cliente te avisa que quer as categorias bagunçadas… Possivelmente isso quer dizer, que ele quer que a categoria “Outros” fique como primeira, mas que as outras continuem em alguma ordem (possivelmente por nome). Agora temos as seguintes soluções:

Criar uma coluna nova na tabela para determinar a ordem da tabela? Ok, é uma ótima idéia, se você possui acesso para alterar a estrutura das tabelas do banco de dados. Sem contar que será necessário reordenar os valores da coluna a cada nova categoria.

Código Nome Ordem
1 Sapatos 9
2 Cintos 6
3 Chapeis 5
4 Calçar 2
5 Casacos 4
6 Camisas 3
7 Meias 7
8 Pijamas 8
9 Outros 1

 

Ou fazer união do registro “Outros” com os outros resultados:

SELECT Código, Nome FROM Categoria
  WHERE Código = 9
UNION
SELECT Código, Nome FROM Categoria
  WHERE Código <> 9

Ok, não funcionou a união… Então o jeito é apelar:

SELECT Código, Nome, '' AS Ordem FROM Categoria
  WHERE Código = 9
UNION
SELECT Código, Nome, Nome AS Ordem FROM Categoria
  WHERE Código <> 9
ORDER BY Ordem

Bem, segue agora minha idéia de solução, ela executa 20% mais rápido, possui um plano de execução bem menor, mais a facilidade de manutenção:

SELECT Código, Nome FROM Categoria
ORDER BY
  CASE Código
    WHEN 8 THEN ''
    ELSE Nome
  END;

Propostas as soluções, agora é escolher a melhor e aplicá-la.

A possibilidade de usar CASE ou funções para ordenação permite solucionar necessidades diversas de ordenação, como gerar uma consulta ordenada aleatoriamente:

SELECT * FROM Tabela
ORDER BY NEWID()

E algumas queries estranhas:

SELECT * FROM Tabela
ORDER BY
  CASE
    WHEN Código > 5 THEN 0 – Código
    ELSE Código
  END;

Se alguém tiver alguma outra proposta, por favor, informem.

Até o próximo post!

Queries para dicionário de dados – Step 2

Continuando o post de Dicionário de dados,

Desde versões antigas do SQL Server são encontradas system view que permitem de várias formas mapear as entidades do banco de dados, desde relacionar as colunas de uma determinada tabela até mapear relacionamentos, índices e arquivos de armazenamento do banco de dados.

Primeiramente, como encontrar os relacionamentos no SQL Server 2000 e superiores:

SELECT
  OBJECT_NAME(foreigns.rkeyid) Parent_Table,
  OBJECT_NAME(foreigns.fkeyid) Child_Table,
  OBJECT_NAME(foreigns.constid) Key_Name,
  parent_columns.name Parent_Col,
  child_columns.name Child_Col
FROM sys.sysforeignkeys foreigns
INNER JOIN sys.syscolumns parent_columns
  ON foreigns.fkeyid = parent_columns.id
  AND foreigns.fkey = parent_columns.colid
INNER JOIN sys.syscolumns child_columns
  ON foreigns.rkeyid = child_columns.id
  AND foreigns.rkey = child_columns.colid
ORDER BY Parent_Table, Child_Table

A mesma funcionalidade no SQL Server 2005/2008:

SELECT
  OBJECT_NAME(foreigns_columns.[referenced_object_id]) Parent_Table,
  OBJECT_NAME(foreigns_columns.[parent_object_id]) Child_Table,
  OBJECT_NAME(foreigns_columns.[constraint_object_id]) Key_Name,
  parent_columns.name Parent_Col,
  child_columns.name Child_KeyCol
FROM sys.foreign_key_columns foreigns_columns
INNER JOIN sys.columns parent_columns
  ON parent_columns.[object_id] = foreigns_columns.[parent_object_id]
  AND parent_columns.[column_id] = foreigns_columns.[parent_column_id]
INNER JOIN sys.columns child_columns
  ON child_columns.[object_id] = foreigns_columns.[referenced_object_id]
  AND child_columns.[column_id] = foreigns_columns.[referenced_column_id]
ORDER BY Parent_Table, Child_Table

A mesma funcionalidade sem o uso da função “OBJECT_NAME”:

SELECT
  parent.name Parent_Table,
  child.name Child_Table,
  foreigns.name FKey_Name,
  parent_columns.name Parent_Col,
  child_columns.name Child_Col
FROM sys.tables parent
INNER JOIN sys.foreign_keys foreigns
  ON parent.[object_id] = foreigns.[referenced_object_id]
INNER JOIN sys.tables child
  ON child.[object_id] = foreigns.[parent_object_id]
INNER JOIN sys.foreign_key_columns foreigns_columns
  ON foreigns_columns.[constraint_object_id] = foreigns.[object_id]
INNER JOIN sys.columns parent_columns
  ON parent_columns.[object_id] = foreigns_columns.[parent_object_id]
  AND parent_columns.[column_id] = foreigns_columns.[parent_column_id]
INNER JOIN sys.columns child_columns
  ON child_columns.[object_id] = foreigns_columns.[referenced_object_id]
  AND child_columns.[column_id] = foreigns_columns.[referenced_column_id]
ORDER BY Parent_Table, Child_Table

Agora, para qualquer banco de dados ANSI (MySQL, SQL Server, SQL Lite, PostgreSQL, Oracle), utilizando as system views do INFORMATION_SCHEMA:

SELECT
  KU.TABLE_NAME Parent_Table,
  KU2.TABLE_NAME Child_Table,
  FK.CONSTRAINT_NAME FKey_Name,
  KU.COLUMN_NAME Parent_Col,
  KU2.COLUMN_NAME Child_Col
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS FK
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KU
  ON KU.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KU2
  ON KU2.CONSTRAINT_NAME = FK.UNIQUE_CONSTRAINT_NAME
  AND KU.ORDINAL_POSITION = KU2.ORDINAL_POSITION

Queries para dicionário de dados – Step 1

Olá pessoal,

Uma coisa complicada quando se modela ou dá suporte a um bancos de dados, é entender a sua estrutura, para isso pensa-se em documentá-los com o Diagrama de Modelo de Entidades e Relacionamentos (DER ou MER) e/ou com o Dicionário de Dados (DD).

Na categoria Visio do Blog (at. https://sqlfromhell.wordpress.com/category/visio/ ) existe uma série de post descrevendo como fazer o Diagrama de Modelo de Entidades e Relacionamentos (DER ou MER), e no próprio Visio também pode ser feito o Dicionário de Dados (DD).

Como nem todos utilizam ou têm acesso ao Visio, neste post vou relacionar as queries utilizadas para consultar a relação de Tabelas, Colunas e Tipos de dados existentes no SQL Server 2000 ao 2008, que são úteis para realizar outras atividades, como “geradores de código” e “relatórios dinâmicos”.

Primeiramente, para relacionar as tabelas do SQL Server podemos fazer uso de system views para SQL Server 2005 e superiores:

SELECT * FROM sys.tables

ou para SQL Server 2000 e superiores:

SELECT * FROM sysobjects
WHERE xtype LIKE 'U'

Para relacionar as tabelas e suas respectivas colunas para SQL Server 2005 e superiores:

SELECT
  T.name as Tabela,
  C.name as Coluna
FROM sys.tables T
INNER JOIN sys.columns C
  ON C.object_id = T.object_id

 ou para SQL Server 2000 e superiores:

SELECT
  T.name as Tabela,
  C.name as Coluna
FROM sysobjects T
INNER JOIN syscolumns C
  ON T.id = C.id
  AND T.xtype LIKE 'U' -- Verifica se o tipo de objeto é uma tabela

Agora uma query from hell para relacionar as colunas ao seus respectivos tipos para SQL Server 2005 e superiores:

SELECT
  T.name as Tabela,
  C.name as Coluna,
  TY.name as Tipo,
  C.max_length, -- Tamanho em bytes, para nvarchar normalmente se divide este valor por 2
  C.precision, -- Para tipos numeric e decimal (tamanho)
  C.scale -- Para tipos numeric e decimal (números após a virgula)
FROM sys.columns C
INNER JOIN sys.tables T
  ON T.object_id = C.object_id
INNER JOIN sys.types TY
  ON TY.user_type_id = C.user_type_id
ORDER BY T.name, C.name

ou para SQL Server 2000 e superiores:

SELECT
  T.name as Tabela,
  C.name as Coluna,
  TY.name as Tipo,
  C.length, -- Tamanho em bytes, para nvarchar normalmente se divide este valor por 2 ou utiliza a 'prec'
  C.prec, -- Para tipos numeric e decimal (tamanho)
  C.scale -- Para tipos numeric e decimal (números após a virgula)
FROM syscolumns C  
INNER JOIN sysobjects T
  ON T.id = C.id
  AND T.xtype LIKE 'U' -- Verifica se o tipo de objeto é uma tabela
INNER JOIN systypes TY
  ON C.usertype = TY.usertype
  AND C.xtype = TY.xtype
ORDER BY T.name, C.name

Agora, para qualquer banco de dados ANSI (MySQL, SQL Server, SQL Lite, PostgreSQL, Oracle), utilizando as system views do INFORMATION_SCHEMA, relacionando as colunas e seus respectivos tipos e tabelas:

SELECT
 TABLE_NAME as Tabela,
 COLUMN_NAME as Coluna,
 DATA_TYPE as Tipo,
 CHARACTER_MAXIMUM_LENGTH, 
 NUMERIC_PRECISION, 
 NUMERIC_SCALE
FROM INFORMATION_SCHEMA.COLUMNS
ORDER BY Tabela, Coluna

ou somente as tabelas:

SELECT
 TABLE_NAME as Tabela
FROM INFORMATION_SCHEMA.TABLES
ORDER BY Tabela

Pessoal até o próximo post!

Replicação – Bug no nome do servidor

Um problema do “cão” me perseguiu em uma consultoria e também o Zavaschi num treinamento, onde não conseguíamos trabalhar com replicação do SQL Server com computadores que tiveram seus nomes alterados.

No caso do Zavaschi, foi porque as VMs do treinamento tinham o mesmo nome e MAC Address, fazendo o servidor DHCP entender que todas VMs eram um computador só. Assim foi necessário mudar o nome das VMs e o MAC Address de suas placas de redes “virtuais”.

No meu caso foi mais simples, alguém instalou o SQL Server e depois mudou o nome do computador.

Mas tanto no meu caso e no caso do Zavaschi, a replicação não funcionava mais…

Foi então que uma luz do submundo do SQL Server nos revelou uma system view das trevas chamada de “sys.servers”, executando um SELECT nela e o que vimos? O nome antigo do servidor ainda estava guardado dentro do SQL Server, what hell was that !?!?

SELECT * FROM sys.servers

Outra luz vinda do submundo nos revelou a solução… Vamos matar o servidor e criar outro!!! Não pegamos os machados e picaretas para atacar o servidor! Mas utilizamos algo pior, usamos o SQL…

EXEC sp_dropserver 'nome_antigo_do_computador'
GO
EXEC sp_addserver 'nome_atual_do_computador ', LOCAL
GO

Reiniciamos o serviço do SQL Server. Daí eu pensei: se não funcionar, estarei no inferno mesmo! Mas felizmente o SQL conseguiu realizar o procedimento corretamente… Ufa…

Depois disso a replicação começou a funcionar corretamente.

Mas minha mente insana teimou por testar uma situação: Se eu somente executar o sp_dropserver (ou executar errado o sp_addserver), depois reiniciar o serviço, o que vai acontecer?

Claro que executei isso em um SQL Server pessoal, daí matei o SQL Server e a partir daí, nem o SQL Server Management Studio funcionava mais com este serviço…

Tive de optar por outra solução, gerei um arquivo SQL com esta query:

EXEC sp_addserver 'nome_atual_do_computador ', LOCAL
GO

E na pasta do “C:\Arquivos de programas\Microsoft SQL Server\90\Tools\Binn”, executei o osql.exe com o arquivo SQL, utilizando o seguinte comando DOS:

osql -U usuario_sa -P senha_do_usuario_sa -i nome_do_arquivo

Reiniciei o serviço do SQL Server 2005 novamente, e as coisas começaram a rodar corretamente.

Pronto! Agora eu podia matar o servidor sem medo!rsss