Contexto DB_ID desde la pila de llamadas más arriba

11

En SQL Server, ¿es posible obtener DB_IDel contexto desde más arriba en la pila de llamadas?

Mi objetivo es crear algunas funciones de utilidad prácticas (y ciertamente hacky) en una base de datos de sandbox de desarrollo que faciliten y concisen obtener los nombres completos de los objetos dados sus nombres cortos o fragmentados, y adicionalmente eliminar objetos usando el mismo nombre corto . Estas funciones de utilidad estarían en una única base de datos de utilidad pero se llamarían desde otras bases de datos en el mismo servidor.

Por lo que puedo ver de las pruebas:

  • ORIGINAL_DB_NAME()según lo previsto, devuelve lo que haya en la cadena de conexión, no el contexto actual (establecido por USE [dbname]).
  • Cuando se llama en una función, DB_NAME()devuelve el nombre de la base de datos donde se define esa función . Otra forma de decir esto es que el contexto dentro de una función o procedimiento almacenado es el de la base de datos en la que se define

Sé que el motor realiza un seguimiento de cada uno de los contextos de la base de datos hacia arriba y hacia abajo en la pila de llamadas (ver prueba a continuación). Entonces, ¿hay alguna forma de acceder a esta información?

Quiero poder encontrar y operar objetos en el contexto de la base de datos de la persona que llama, aunque el código de ejecución no esté en la misma base de datos. Por ejemplo:

use SomeDB
EXEC util.dbo.frobulate_table 'my_table'

Sé que solo puedo hacer

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

Pero tengo mucha curiosidad si es posible consultar la pila de llamadas de esta manera.

Actualización / nota

Leí y descargué el código del blog de Gabriel McAdams . Esto proporciona un registro de la identificación del procedimiento de llamada arriba y abajo de la pila, pero aún asume que todo está en la misma base de datos.

Prueba de que el servidor SQL recuerda la pila de llamadas de contexto DB arriba y abajo

Ejemplo: en un servidor de desarrollo con bases de datos TestDB1 y 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 

El proceso 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
fuente
Sería posible a través de eventos extendidos, pero solo como una novedad realmente. No es algo para uso de producción serio. Incluso si conoce el nombre de la base de datos, ¿cómo lo usaría de todos modos? ¿Tiene todo en sql dinámico con un USE xyz;precedente?
Martin Smith
Honestamente, no puedo decir que tenga un caso sólido de por qué esto sería necesario . Lo encontré muy interesante y si lo descubro, lo pondré en dos pequeños y prácticos procedimientos que uso en mi base de datos de desarrollo de sandbox: Uno que obtiene el nombre completo de un objeto dado el fragmento más corto reconocible del nombre (como en mi primer ejemplo en la pregunta), y otro que mata objetos usando la otra función para obtener el nombre completo y también usa el tipo del objeto identificado para generar una DROPdeclaración.
Joshua Honig
@SQLKiwi Pregunta actualizada en consecuencia. Gracias por la otra respuesta, también. Ya tengo una variedad de funciones CLR para la manipulación de cadenas, por lo que este debería ser el siguiente paso natural para mí.
Joshua Honig

Respuestas:

4

No puede lograr esto con funciones en una base de datos de utilidades. Sin embargo, puede crear procedimientos de utilidad en la base de datos maestra, marcarlos como objetos del sistema y llamarlos desde el contexto de cualquier base de datos en su sistema. Un artículo con un buen ejemplo se puede encontrar en esta ubicación .

nabrond
fuente
Esto es novedoso pero un poco peligroso. Es fácil perder el rastro de configuraciones de servidor personalizadas como esta a medida que migra a diferentes entornos (por ejemplo, un nuevo servidor o una nueva versión de SQL Server).
Riley Major