Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Pobierz definicję kolumny dla zestawu wyników procedury składowanej

Załóżmy, że masz procedurę składowaną w tempdb:

USE tempdb;
GO

CREATE PROCEDURE dbo.my_procedure
AS
BEGIN
    SET NOCOUNT ON;

    SELECT foo = 1, bar = 'tooth';
END
GO

Istnieje dość zawiły sposób określania metadanych, które wygeneruje procedura składowana. Istnieje kilka zastrzeżeń, w tym procedura może wyprowadzić tylko jeden zestaw wyników, a jeśli nie można go dokładnie określić, zostanie dokonane najlepsze przypuszczenie, jeśli chodzi o typ danych. Wymaga użycia OPENQUERY i serwer połączony z pętlą zwrotną z 'DATA ACCESS' właściwość ustawiona na true. Możesz sprawdzić sys.servers, aby sprawdzić, czy masz już prawidłowy serwer, ale stwórzmy taki ręcznie o nazwie loopback :

EXEC master..sp_addlinkedserver 
    @server = 'loopback',  
    @srvproduct = '',
    @provider = 'SQLNCLI',
    @datasrc = @@SERVERNAME;

EXEC master..sp_serveroption 
    @server = 'loopback', 
    @optname = 'DATA ACCESS',
    @optvalue = 'TRUE';

Teraz, gdy możesz zapytać o to jako serwer połączony, możesz użyć wyniku dowolnego zapytania (w tym wywołania procedury składowanej) jako zwykłego SELECT . Możesz to zrobić (zwróć uwagę, że przedrostek bazy danych to ważne, w przeciwnym razie otrzymasz błąd 11529 i 2812):

SELECT * FROM OPENQUERY(loopback, 'EXEC tempdb.dbo.my_procedure;');

Jeśli możemy wykonać SELECT * , możemy również wykonać SELECT * INTO :

SELECT * INTO #tmp FROM OPENQUERY(loopback, 'EXEC tempdb.dbo.my_procedure;');

A kiedy już ta tabela #tmp istnieje, możemy określić metadane, mówiąc (zakładając, że SQL Server 2005 lub nowszy):

SELECT c.name, [type] = t.name, c.max_length, c.[precision], c.scale
  FROM sys.columns AS c
  INNER JOIN sys.types AS t
  ON c.system_type_id = t.system_type_id
  AND c.user_type_id = t.user_type_id
  WHERE c.[object_id] = OBJECT_ID('tempdb..#tmp');

(Jeśli używasz SQL Server 2000, możesz zrobić coś podobnego z kolumnami systemowymi, ale nie mam pod ręką instancji 2000 do sprawdzenia równoważnego zapytania).

Wyniki:

name      type    max_length precision scale
--------- ------- ---------- --------- -----
foo       int              4        10     0
bar       varchar          5         0     0

W Denali będzie to dużo, dużo, dużo łatwiejsze. Ponownie, nadal istnieje ograniczenie pierwszego zestawu wyników, ale nie musisz konfigurować połączonego serwera i przeskakiwać przez wszystkie te obręcze. Możesz po prostu powiedzieć:

DECLARE @sql NVARCHAR(MAX) = N'EXEC tempdb.dbo.my_procedure;';

SELECT name, system_type_name
    FROM sys.dm_exec_describe_first_result_set(@sql, NULL, 1);

Wyniki:

name      system_type_name
--------- ----------------
foo       int             
bar       varchar(5)      

Do czasu Denali sugeruję, że łatwiej byłoby po prostu zakasać rękawy i samodzielnie wymyślić typy danych. Nie tylko dlatego, że wykonywanie powyższych kroków jest żmudne, ale także dlatego, że jest znacznie bardziej prawdopodobne, że dokonasz poprawnego (lub przynajmniej dokładniejszego) odgadnięcia niż zrobi to silnik, ponieważ odgadnięcia typu danych, które wykonuje silnik, będą oparte na czasie wykonywania wyjście, bez żadnej zewnętrznej wiedzy o domenie możliwych wartości. Ten czynnik pozostanie również prawdziwy w Denali, więc nie miej wrażenia, że ​​nowe funkcje odkrywania metadanych są ostateczne, po prostu sprawiają, że powyższe jest nieco mniej nużące.

Aha i kilka innych potencjalnych problemów z OPENQUERY , zobacz artykuł Erlanda Sommarskoga tutaj:

http://www.sommarskog.se/share_data.html#OPENQUERY



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nie można użyć predykatu CONTAINS lub FREETEXT w tabeli lub widoku indeksowanym, ponieważ nie jest indeksowany pełnotekstowo

  2. Znaki nieliczbowe, które zwracają wartość dodatnią podczas używania ISNUMERIC() w SQL Server

  3. Wdrażanie stronicowania za pomocą OFFSET FETCH NEXT w SQL Server

  4. Kolejność wykonania zapytania SQL

  5. Błąd R DBI ODBC:nanodbc/nanodbc.cpp:3110:07009:[Microsoft][Sterownik ODBC 13 dla programu SQL Server]Nieprawidłowy indeks deskryptora