No artigo anterior, eu apresentei como localizar um campo num banco de dados do SQL Server 2012 conhecendo apenas o nome do campo. Mas existem situações em que precisamos identificar um campo em que nem mesmo o nome é conhecido.
Algumas vezes, os usuários precisam de ajuda para identificar campos (seu nome, tabela e esquema), sabendo apenas o conteúdo do campo. Usuários não têm culpa se os bancos de dados são mal documentados e/ou se o arquiteto do banco saiu da empresa. E você, como DBA e profissional dedicado, precisa encontrar soluções para os problemas da empresa.
O script que apresento a seguir foi criado para solucionar esse tipo de cenário. A ideia aqui é usar tabelas de sistemas para gerar uma consulta SQL que fará a pesquisa em todos os campos que suportam o tipo de dados pesquisado. Ou seja, o script resolve o problema pela “força bruta”.
O exemplo a seguir usa a base AdventureWorks2012 e faz uma varredura de todos os campos com tipos de dados que aceitem cadeias de caracteres para encontrar qual deles contém a palavra “Paul”.
Para isso, eu usei as seguintes tabelas:
- sys.schemas
- sys.all_objects
- sys.all_columns
- sys.types
A seguir, eu descrevo em detalhes como funciona a consulta nas tabelas de sistema e como ela gera o texto equivalente ao script de uma nova consulta:
- a consulta nas tabelas de sistema gera uma nova e única declaração SQL, que então será usada para pesquisar todos os campos desejados
- a consulta nas tabelas de sistema concatena cadeias de caracteres fixos e os valores dos campos das próprias tabelas de sistema, de tal modo que cada registro da listagem final é, por si só, uma nova declaração SQL
- ao final de cada linha da listagem, teremos a palavra UNION para que a declaração SQL dessa linha possa ser executada junto com a declaração da linha seguinte
- para facilitar a lógica da consulta, deve-se lembrar que o último registro da listagem também inclui a palavra UNION, mas esta deve ser desconsiderada quando a nova declaração for executada
- apenas tabelas de usuário precisam ser consultadas (sys.all_objects.type = ‘U’)
- são considerados apenas campos cujo tipo de dados aceite cadeias de caracteres (sys.types in (CHAR, VARCHAR, NCHAR & NVARCHAR))
- nas consultas geradas, a palavra “Paul” pode ser encontrada em qualquer posição do campo ( campo like ‘%Paul%’)
- as consultas geradas devem funcionar mesmo quando tabelas e/ou campos tenham nomes com espaços em branco (escrever nomes de tabelas e campos entre chaves ‘[‘ e ‘]’)
Juntando tudo isso, temos a seguinte consulta:
SELECT 'select ''[' + S.NAME + ']'' AS ESQUEMA, ''[' + O.NAME + ']'' AS TABELA, ' + '''[' + C.NAME + ']'' AS COLUNA ' + ' from [' + S.NAME + '].[' + O.NAME + ']' + ' where [' + C.NAME + '] like ''%Paul%'' union ' FROM SYS.ALL_OBJECTS O INNER JOIN SYS.SCHEMAS S ON O.SCHEMA_ID = S.SCHEMA_ID INNER JOIN SYS.ALL_COLUMNS C ON O.OBJECT_ID=C.OBJECT_ID INNER JOIN SYS.TYPES T ON C.USER_TYPE_ID=T.USER_TYPE_ID WHERE O.TYPE='U' AND T.NAME IN ('char', 'nchar', 'varchar', 'nvarchar') ORDER BY S.NAME, O.NAME, C.NAME
Essa consulta gerou um script de 71 linhas. Para fins ilustrativos, mostro a seguir a primeira e a última linha do script, já considerando que a palavra UNION precisa ser excluída manualmente da última linha do script.
select '[dbo]' AS ESQUEMA, '[AWBuildVersion]' AS TABELA, '[Database Version]' AS COLUNA from [dbo].[AWBuildVersion] where [Database Version] like '%Paul%' union ...
select '[sys]' AS ESQUEMA, '[trace_xe_event_map]' AS TABELA, '[xe_event_name]' AS COLUNA from [sys].[trace_xe_event_map] where [xe_event_name] like '%Paul%'
Finalmente, eu executo essa consulta para obter a listagem de todos os campos e tabelas do banco de dados AdventureWorks2012 que possuem a palavra “Paul” em seu conteúdo, como mostro a seguir.
ESQUEMA TABELA COLUNA
—————- ————————————— ————————-
[HumanResources] [Employee] [LoginID]
[Person] [Address] [AddressLine1]
[Person] [EmailAddress] [EmailAddress]
(3 row(s) affected)
Graças a esse recurso, foi possível reduzir a pesquisa de identificação de um campo a apenas 3 possíveis candidatos, o que facilita enormemente o trabalho.
Contudo, é importante observar que esta é uma consulta pesada. Ela pesquisa todos os campos do tipo cadeia de caracteres usando o operador LIKE, que por si só já tem um impacto significativo em performance.
Sendo assim, é recomendável que se tenha o cuidado de executar consultas dessa natureza em horários em que o banco de dados tenha pouca atividade.
Por hoje é só, espero que tenha gostado desta dica. Até a próxima!