sql >> Databáze >  >> RDS >> Sqlserver

Načíst definici sloupce pro sadu výsledků uložené procedury

Řekněme, že máte uloženou proceduru v tempdb:

USE tempdb;
GO

CREATE PROCEDURE dbo.my_procedure
AS
BEGIN
    SET NOCOUNT ON;

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

Existuje poměrně spletitý způsob, jak určit metadata, která uložená procedura vydá. Existuje několik upozornění, včetně toho, že postup může vydávat pouze jednu sadu výsledků a že pokud nelze přesně určit typ dat, bude proveden nejlepší odhad. Vyžaduje použití OPENQUERY a server propojený se zpětnou smyčkou s 'DATA ACCESS' vlastnost nastavena na true. Můžete zkontrolovat sys.servers, abyste zjistili, zda již máte platný server, ale pojďme si jej vytvořit ručně s názvem loopback :

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

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

Nyní, když to můžete dotazovat jako propojený server, můžete použít výsledek jakéhokoli dotazu (včetně volání uložené procedury) jako běžný SELECT . Takže to můžete udělat (všimněte si, že předpona databáze je důležité, jinak se zobrazí chyba 11529 a 2812):

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

Pokud můžeme provést SELECT * , můžeme také provést SELECT * INTO :

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

A jakmile tato #tmp tabulka existuje, můžeme určit metadata tak, že řekneme (za předpokladu, že SQL Server 2005 nebo vyšší):

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');

(Pokud používáte SQL Server 2000, můžete udělat něco podobného se systémovými sloupci, ale nemám k dispozici instanci 2000 pro ověření ekvivalentního dotazu.)

Výsledky:

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

V Denali to bude mnohem, mnohem, mnohem jednodušší. Opět zde stále platí omezení pro první sadu výsledků, ale nemusíte nastavovat propojený server a přeskakovat všechny ty obruče. Můžete jen říct:

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);

Výsledky:

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

Až do Denali navrhuji, že by bylo jednodušší vyhrnout si rukávy a zjistit datové typy sami. Nejen proto, že je zdlouhavé procházet výše uvedenými kroky, ale také proto, že je mnohem pravděpodobnější, že uděláte správný (nebo alespoň přesnější) odhad než motor, protože datový typ, který motor odhaduje, bude založen na době běhu. výstup, bez jakékoli vnější znalosti oboru možných hodnot. Tento faktor zůstane pravdivý i v Denali, takže se nenechte domnívat, že nové funkce zjišťování metadat jsou úplným koncem, jen dělají výše uvedené o něco méně únavným.

Jo a pro některé další potenciální problémy s OPENQUERY , viz článek Erlanda Sommarskoga zde:

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



  1. Jak funguje clock_timestamp() v PostgreSQL

  2. Rozdíl mezi FIELD() a FIND_IN_SET() v MySQL

  3. nelze načíst oci8 -> Závažná chyba:Volání nedefinované funkce oci_connect()

  4. Jak změnit názvy tabulek MySQL na serveru Linux tak, aby nerozlišovaly malá a velká písmena?