Já trabalhei em um ambiente SQL Server onde o log fazia parte de nossos procedimentos armazenados para capturar o início/fim da execução, valores de parâmetro e mensagens de erro que achei muito úteis e é algo que pretendo introduzir em um novo ambiente.
As tabelas usadas para esse registro pareciam algo abaixo, os parâmetros foram capturados usando INSERT
instruções em uma tabela com os valores sendo implicitamente convertidos em NVARCHAR
.
CREATE TABLE dbo.Execution
(
Id INT IDENTITY(1,1) NOT NULL
, SchemaName NVARCHAR(128) NOT NULL
, ProcedureName NVARCHAR(128) NOT NULL
, ExecutionStart DATETIME NOT NULL
, ExecutionEnd DATETIME NULL
, ExecutionFailed BIT NOT NULL
)
CREATE TABLE dbo.ExecutionError
(
Id INT IDENTITY(1,1) NOT NULL
, ExecutionId INT NOT NULL
, CustomErrorMessage NVARCHAR(8000) NULL
, SqlErrorMessage NVARCHAR(8000) NULL
)
CREATE TABLE dbo.ExecutionParameter
(
Id INT IDENTITY(1,1) NOT NULL
, ExecutionId INT NOT NULL
, ParameterName NVARCHAR(128) NOT NULL
, ParameterValue NVARCHAR(MAX) NULL
)
Tenho reconsiderado a ExecutionParameter
tabela com a possibilidade de usar um SQL_VARIANT
tipo de dados para que eu possa obter o tipo de dados base, se necessário, para fins de análise e relatório, sem ter que adivinhar com base no nome/valor.
No entanto, isso não funcionaria para parâmetros que possuem um tipo de dados de NVARCHAR(MAX)
ou VARCHAR(MAX)
e, portanto, precisariam ainda ter a NVARCHAR(MAX)
coluna lá, o que seria NULL
a maior parte do tempo.
O uso de SQL_VARIANT
é tentador, mas sinto que a estrutura original da tabela funciona bem e não pode ser melhorada sem tornar o processo mais complicado.
Isso é algo que você fez anteriormente, em caso afirmativo, como você o implementou? Você pode ver espaço para melhorias no esquema acima sem torná-lo excessivamente complicado?
Talvez uma tabela adicional com detalhes do procedimento armazenado e seus parâmetros que possam ser referenciados? Embora eu ache que isso seria difícil de manter e tornar-se confuso, pois os procedimentos armazenados são modificados com o tempo.
Sim, fizemos esse tipo de coisa em uma empresa em que trabalhei há alguns anos. Embora tenhamos feito isso apenas para registro de erros, era o mesmo conceito geral. Você só precisa escrever a instrução SELECT que inclui todos os parâmetros de entrada, usar
FOR XML
, e armazená-la em uma variável que pode ser inserida em suaExecution
tabela em um novo campo:Parameters XML NULL
. E então você pode descartar aExecutionParameter
mesa.Tente o seguinte, pois ele mostra três maneiras de gerar o XML: baseado em atributo, baseado em elemento e baseado em elemento, incluindo elementos NULL. O comportamento padrão de
FOR XML
é indicarNULL
valores não incluindo o atributo ou elemento. Mas se você estiver fazendo XML baseado em elemento e quiser que os parâmetros sejam exibidos mesmo que sejamNULL
, será necessário especificarXSINIL
naFOR XML
cláusula. A capacidade de incluir um indicador paraNULL
não está disponível em XML baseado em atributo.Observe que não há uma grande diferença entre o XML baseado em atribuição e o XML baseado em elemento padrão (padrão = não inclui
NULL
itens) em termos de tamanho de armazenamento (conforme mostrado no exemplo abaixo). Ao visualizar o XML, parece que há muito mais "inchaço" com base em elementos, e esse seria o caso se os dados fossem armazenados em umNVARCHAR
campo ou arquivo de texto. Mas o tipo deXML
dados usa um método otimizado para armazenar os dados internamente, de uma forma que não pode ser vista, mas é claramente indicada naDATALENGTH
saída resultante.Há, no entanto, um pequeno aumento de tamanho ao usar a
XSINIL
opção de XML baseado em elementos e precisa acompanhar osNULL
elementos que são excluídos dos outros dois tipos. O aumento no tamanho é devido a uma ocorrência única para declarar oxsi
namespace no elemento raiz e, em seguida, uma ocorrência porNULL
elemento.Valores XML retornados:
Notas Adicionais:
Para as colunas
SchemaName
eProcedureName
, eu usariasysname
como o tipo de dados, pois é assim que é definido nas tabelas do sistema. E certifique-se de usar letras minúsculassysname
, pois é um alias que residemaster
e os servidores com um agrupamento padrão binário ou com distinção entre maiúsculas e minúsculas não poderão encontrar esse alias se não estiver todo em letras minúsculas. Seu servidor atual pode não diferenciar maiúsculas de minúsculas, mas ainda é um bom hábito adquirir ao usar arquivossysname
.Para a
ExecutionError
tabela, certifique-se de incluirINT
colunas para capturar:ERROR_LINE()
,ERROR_NUMBER()
,ERROR_STATE()
eERROR_SEVERITY()
.Não, você não deseja usar
SQL_VARIANT
, pois isso o impede de armazenar os tipos de LOB:VARCHAR(MAX)
,NVARCHAR(MAX)
,VARBINARY(MAX)
eXML
.Não, você não pode usar
NVARCHAR(8000)
porqueNVARCHAR
tem um tamanho máximo de 4000, a menos que você useMAX
.