Tymczasowa globalna procedura zwraca w @@PROCID numer obiektu w tempdb, ale OBJECT_NAME(@@PROCID) zwróci błędne dane -_-

Dobra. Nie wiem czemu tak jest…

Spróbowałem stworzyć globalną procedurę tymczasową, chciałem pobrać jej nazwę w kodzie. Dostawałem wyniki bez sensu (zwracało mi nazwę jakiejś procedury z bazy, na której tworzyłem ##).

Zrobiłem zatem pętlę, która co sekundę tworzy ##DUPA od nowa i zwraca jego @@PROCID i pobraną nazwę z danej bazy. Oczywiście powinno być NULL (## istnieje tylko w tempdb). Ale takiego wyniku się nie spodziewałem…

USE SSISDB;
GO
DECLARE @SQL NVARCHAR(MAX) = '
CREATE PROC ##DUPA
AS
    DECLARE @ProcName sysname = OBJECT_NAME(@@PROCID);
    RAISERROR(''Procedure id: %d, name: %s'',0,1,@@PROCID,@ProcName) WITH NOWAIT;
';


WHILE ( 1 = 1 )
    BEGIN

        EXEC (@SQL);
        EXEC ##DUPA;
        DROP PROC ##DUPA;
        WAITFOR DELAY '00:00:01';
    END;

 

Czy ktoś ma pomysł czemu @@PROCID zwraca takie wyniki? 😀

 

#edit 2018.06.03

Jak słusznie zauważył Michał Krużel, @@PROCID zwraca id prawidłowe, pochodzi ono ze źródła w jakim znajduje się procedura, czyli bazy tempdb.

Problem nie leży zatem w samym @@PROCID, a w OBJECT_NAME(), które wykonuje się w kontekście obecnej bazy, nie na źródle.

3 myśli na temat “Tymczasowa globalna procedura zwraca w @@PROCID numer obiektu w tempdb, ale OBJECT_NAME(@@PROCID) zwróci błędne dane -_-

  1. …bo wykonujesz to w kontekście ssisdb a powinieneś w kontekście tempdb, to że procedura jest globalna nie znaczy że jej id znajdzie się w każdej bazie, ono (id) jest tylko w tempdb ( i całe szczęście że tylko tam ) , wyniki są przypadkowe , w pewnym momencie przestały by się nakładać i dostałbyś nulle
    pozdrawiam
    MK

    1. no właśnie byłem święcie przekonany, że skoro ## jest tylko w tembdb, to kontekst działania @@procid i OBJECT_NAME powinien być względem bazy tymczasowej, czyli tej z której uruchamiam procedurę.

      Widzisz, żeby zrozumieć mój ból 😉 trzeba pokazać jak to działa na przykładzie zwykłej procedury :]

      Zobacz, jeśli utworzysz procedurę w przykładowej NORMALNEJ bazie o nazwie np. moja_baza:

      USE moja_baza
      GO

      CREATE OR ALTER PROCEDURE testowa AS
      SELECT @@PROCID
      SELECT OBJECT_NAME(@@PROCID)

      i uruchomisz ją z innej bazy. np. SSISDB dostaniesz PRAWIDŁOWY wynik podobny do tego:
      USE SSISDB
      GO
      EXEC moja_baza.dbo.testowa

      885578193
      testowa

      Jest zatem poprawnie wyniesiony ID procedury z bazy moja_baza, również sprawdzenie nazwy wykonało się względem niej, choć execute był na innej!

      ALE, jeśli uruchomisz to w kontekście tempowej, OBJECT_NAME nie zadziała tak jak zadziałał na powyższej procedurze, tylko weźmie kontekst OBECNEJ bazy, choć @@PROCID zwróci ID z temdb:

      USE SSISDB;
      GO
      DECLARE @SQL NVARCHAR(MAX) = ’
      CREATE PROC ##testowa
      AS
      DECLARE @ProcName sysname = OBJECT_NAME(@@PROCID);
      RAISERROR(”Procedure id: %d, name: %s”,0,1,@@PROCID,@ProcName) WITH NOWAIT;
      ’;

      WHILE
      (…)

      wynik:

      Procedure id: 821577965, name: FK_ObjectParameters_ProjectVersionLsn_ObjectVersions
      Procedure id: 837578022, name: environments
      Procedure id: 853578079, name: PK_Environments
      Procedure id: 869578136, name: Unique_Folder_Environment
      (…)

      I faktycznie tytuł wpisu jest mylący! Bo tu nie chodzi o to, że zwraca ID z innej bazy (czyli tempdb), tylko miesza w OBJECT_NAME. Jak widać wtedy też do końca nie wiedziałem z czym walczę ;]

Dodaj komentarz