Contexto DB_ID da pilha de chamadas mais avançada

11

No SQL Server, é possível obter DB_IDo contexto mais distante da pilha de chamadas?

Meu objetivo é criar algumas funções úteis (e reconhecidamente hacky) em um banco de dados de sandbox de desenvolvimento que facilite e concise obter os nomes totalmente qualificados dos objetos, com nomes abreviados ou fragmentados, além de excluir objetos usando o mesmo nome abreviado . Essas funções de utilitário estariam em um único banco de dados de utilitário, mas chamado de outros bancos de dados no mesmo servidor.

Pelo que posso ver nos testes:

  • ORIGINAL_DB_NAME()como pretendido retorna o que estava na cadeia de conexão, não o contexto atual (definido por USE [dbname]).
  • Quando chamada em uma função, DB_NAME()retorna o nome do banco de dados em que a função está definida . Outra maneira de dizer isso é que o contexto dentro de uma função ou procedimento armazenado é o do banco de dados no qual está definido

Sei que o mecanismo controla cada um dos contextos do banco de dados para cima e para baixo na pilha de chamadas (veja a prova abaixo). Então, existe alguma maneira de acessar essas informações?

Quero poder encontrar e operar objetos no contexto do banco de dados do chamador, mesmo que o código em execução não esteja no mesmo banco de dados. Por exemplo:

use SomeDB
EXEC util.dbo.frobulate_table 'my_table'

Eu sei que posso fazer

EXEC util.dbo.frobulate_table 'SomeDB.dbo.my_table'

Mas estou realmente curioso para saber se é possível consultar a pilha de chamadas dessa maneira.

Atualização / observação

Eu li e baixei o código do blog de Gabriel McAdams . Isso fornece um registro do ID do procedimento de chamada para cima e para baixo na pilha, mas ainda assume que tudo está no mesmo banco de dados.

A prova de que o SQL Server lembra a pilha de chamadas para cima e para baixo do contexto do banco de dados

Exemplo: Em um servidor dev com bancos de dados TestDB1 e TestDB2

use TestDB1
GO
CREATE FUNCTION dbo.ECHO_DB_NAME() RETURNS nvarchar(128) BEGIN RETURN DB_NAME() END
GO

use TestDB2
GO
CREATE PROCEDURE dbo.ECHO_STACK AS 
BEGIN
    DECLARE @name nvarchar(128)
    SET @name = DB_NAME()
    PRINT 'Before, DB_NAME inside dbo.ECHO_STACK : ' + @name
    SET @name = TestDB1.dbo.ECHO_DB_NAME()        
    PRINT 'TestDB1.dbo.ECHO_DB_NAME returned     : ' + @name
    SET @name = DB_NAME()
    PRINT 'After, DB_NAME inside dbo.ECHO_STACK  : ' + @name
END
GO

use master
SELECT DB_NAME()  -- Returns 'master'
EXEC TestDB2.dbo.ECHO_STACK 

O processo ECHO_STACK imprime:

Before, DB_NAME inside dbo.ECHO_STACK : TestDB2
TestDB1.dbo.ECHO_DB_NAME returned     : TestDB1
After, DB_NAME inside dbo.ECHO_STACK  : TestDB2
Joshua Honig
fonte
Seria possível através de eventos prolongados, mas apenas como uma novidade realmente. Não é algo para uso sério na produção. Mesmo se você souber o nome do banco de dados, como você o usaria? Tem tudo no sql dinâmico com um USE xyz;precedente?
Martin Smith
Honestamente, não posso dizer que tenho um argumento sólido sobre por que isso seria necessário . Eu achei muito interessante e se eu fazer descobrir isso vou colocá-lo em duas procs pouco útil que eu uso no meu banco de dados sandbox dev: Um que recebe o nome completo de um objeto dado o menor fragmento reconhecível do nome (como em meu primeiro exemplo na pergunta) e outro que mata objetos usando a outra função para obter o nome completo e também usa o tipo do objeto identificado para gerar uma DROPdeclaração.
21412 Joshua Honig
@SQLKiwi Pergunta atualizada de acordo. Obrigado pela outra resposta também. Eu já tenho uma variedade de funções CLR para manipulação de strings, portanto esse deve ser o próximo passo natural para mim.
precisa

Respostas:

4

Você não pode fazer isso com funções em um banco de dados utilitário. No entanto, você pode criar procedimentos utilitários no banco de dados mestre, marcá-los como objetos do sistema e chamá-los a partir do contexto de qualquer banco de dados no seu sistema. Um artigo com um bom exemplo pode ser encontrado neste local .

nabrond
fonte
Isso é novo, mas um pouco perigoso. É fácil perder o controle de configurações personalizadas de servidor como esta à medida que você migra para diferentes ambientes (por exemplo, novo servidor ou nova versão do SQL Server).
Riley Major