Dans SQL Server, est-il possible d'extraire DB_ID
le contexte du plus haut de la pile d'appels?
Mon objectif est de créer des fonctions utilitaires pratiques (et certes hacky) dans une base de données de bac à sable de développement qui permettent d'obtenir facilement et concis les noms complets des objets en fonction de leurs noms courts ou fragmentés, et en outre de supprimer des objets en utilisant le même nom court . Ces fonctions utilitaires se trouveraient dans une seule base de données utilitaires mais appelées à partir d'autres bases de données sur le même serveur.
D'après ce que je peux voir des tests:
ORIGINAL_DB_NAME()
comme prévu renvoie tout ce qui était dans la chaîne de connexion, pas le contexte actuel (défini parUSE [dbname]
).- Lorsqu'elle est appelée dans une fonction, elle
DB_NAME()
renvoie le nom de la base de données où cette fonction est définie . Une autre façon de le dire est que le contexte à l'intérieur d'une fonction ou d'une procédure stockée est celui de la base de données dans laquelle il est défini
Je sais que le moteur garde une trace de chacun des contextes de base de données de haut en bas de la pile d'appels (voir ci-dessous pour la preuve). Existe-t-il un moyen d'accéder à ces informations?
Je veux pouvoir trouver et opérer sur des objets dans le contexte de la base de données de l'appelant, même si le code d'exécution n'est pas dans la même base de données. Par exemple:
use SomeDB
EXEC util.dbo.frobulate_table 'my_table'
Je sais que je peux juste faire
EXEC util.dbo.frobulate_table 'SomeDB.dbo.my_table'
Mais je suis vraiment curieux de savoir s'il est possible d'interroger la pile d'appels de cette façon.
Mise à jour / note
J'ai lu et téléchargé le code sur le blog de Gabriel McAdams . Cela fournit un enregistrement de l'ID de la procédure d'appel de haut en bas de la pile, mais suppose toujours que tout se trouve dans la même base de données.
La preuve que SQL Server se souvient de la pile d'appels de haut en bas du contexte de base de données
Exemple: sur un serveur de développement avec les bases de données TestDB1 et 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
Le proc 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
la source
USE xyz;
précédent?DROP
déclaration.Réponses:
Vous ne pouvez pas accomplir cela avec des fonctions dans une base de données utilitaire. Vous pouvez cependant créer des procédures utilitaires dans la base de données master, les marquer en tant qu'objets système et les appeler à partir du contexte de n'importe quelle base de données sur votre système. Un article avec un bon exemple peut être trouvé à cet endroit .
la source