Estou tentando produzir um relatório de uso para alguns procedimentos armazenados em meu banco de dados. A view view sys.dm_exec_procedure_stats contém um pouco do que eu preciso, então decidi começar por aqui.
Metadados de procedimento de chaves do SQL Server por ID de objeto. Conheço apenas os nomes dos procedimentos, então primeiro tenho que mapear os nomes para IDs usando a função OBJECT_ID .
Existem vários procedimentos para verificar, então quero colocar seus nomes em uma tabela temporária antes de processá-los.
Achei que seria legal pegar o id do objeto de uma coluna computada na tabela temporária, então criei uma tabela assim:
USE msdb;
GO
CREATE TABLE #procs (
name SYSNAME,
[object_id] AS OBJECT_ID(name)
);
INSERT INTO #procs (name) VALUES ('dbo.sp_send_dbmail');
INSERT INTO #procs (name) VALUES ('dbo.sp_add_job');
INSERT INTO #procs (name) VALUES ('dbo.sp_start_job');
Com essa tabela no lugar, a maneira óbvia de obter as contagens de execução ficou assim:
SELECT #procs.name, execution_count
FROM sys.dm_exec_procedure_stats AS procstats
INNER JOIN #procs ON #procs.[object_id] = procstats.[object_id]
ORDER BY execution_count DESC;
Mas ele retorna um conjunto de resultados vazio!
Esta consulta mostra por que o conjunto de resultados está vazio:
SELECT name, [object_id]
FROM #procs;
A coluna object_id é NULL, então uma junção interna não produzirá linhas:
name object_id
-------------------- -----------
dbo.sp_send_dbmail NULL
dbo.sp_add_job NULL
dbo.sp_start_job NULL
Não é que as colunas calculadas sejam quebradas para tabelas temporárias. Se eu adicionar uma coluna computada para inverter o nome, ela produzirá o valor correto quando selecioná-la:
ALTER TABLE #procs ADD reverse_name AS REVERSE(name);
SELECT name, [object_id], reverse_name
FROM #procs;
Resultado:
name object_id reverse_name
-------------------- ----------- ---------------------
dbo.sp_send_dbmail NULL liambd_dnes_ps.obd
dbo.sp_add_job NULL boj_dda_ps.obd
dbo.sp_start_job NULL boj_trats_ps.obd
Por que OBJECT_ID retorna NULL aqui?
Uma função de metadados mencionada em uma coluna computada em uma
#temp
tabela irá referenciartempdb.sys.objects
, nãoyourdatabase.sys.objects
, já que a tabela é criada emtempdb
. Tente adicionar o prefixo do banco de dados ao insert, e isso fará com que vocêOBJECT_ID
o encontre no lugar certo:Resultados:
Você está fazendo algo excessivamente complicado e trivial. Remova a coluna computada, insira
OBJECT_ID
explicitamente.O que acontece é que você está perdendo o controle sobre onde é
OBJECT_ID
avaliado (em qual contexto do banco de dados).OBJECT_ID
retornará valores diferentes, para o mesmo nome, em DBS diferentes ou pode retornar NULL para nomes que não correspondem ao contexto de execução atual (db). Ao adicionar a avaliação em uma#temp
tabela, você não pode ter certeza de onde a avaliação ocorre. Está emtempdb
? emmsdb
? No banco de dados atual? Bem, parece que não está onde você esperava, com certeza...Abandone a esperteza extravagante, atenha-se ao KISS.
Em seguida, corrija seu
`JOIN #procs ON #procs.[object_id] = procstats.[object_id]
, pois está incorreto. Você precisa entrar emobject_id
edatabase_id
.