En SQL Server, ¿es posible obtener DB_ID
el 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 porUSE [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
fuente
USE xyz;
precedente?DROP
declaración.Respuestas:
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 .
fuente