[Právě jsem si uvědomil, že jsem na tuto otázku již odpovídal]
To pro uloženou proceduru je mnohem složitější než pro pohled nebo tabulku. Jedním z problémů je, že uložená procedura může mít několik různých cest kódu v závislosti na vstupních parametrech a dokonce i věcech, které nemůžete ovládat, jako je stav serveru, denní doba atd. Takže například to, co byste očekávali jako výstup pro tato uložená procedura? Co když existuje více sad výsledků bez ohledu na podmínky?
CREATE PROCEDURE dbo.foo
@bar INT
AS
BEGIN
SET NOCOUNT ON;
IF @bar = 1
SELECT a, b, c FROM dbo.blat;
ELSE
SELECT d, e, f, g, h FROM dbo.splunge;
END
GO
Pokud vaše uložená procedura nemá cesty kódu a jste si jisti, že vždy uvidíte stejnou sadu výsledků (a můžete předem určit, jaké hodnoty by měly být dodány, pokud má uložená procedura nepovinné parametry), ukažme si jednoduchý příklad:
CREATE PROCEDURE dbo.bar
AS
BEGIN
SET NOCOUNT ON;
SELECT a = 'a', b = 1, c = GETDATE();
END
GO
POUZE FMTON
Jedním ze způsobů je udělat něco takového:
SET FMTONLY ON;
GO
EXEC dbo.bar;
Získáte tak prázdnou sadu výsledků a vaše klientská aplikace se může podívat na vlastnosti této sady výsledků a určit názvy sloupců a datové typy.
Nyní je spousta problémů s SET FMTONLY ON;
že se zde nebudu rozepisovat, ale přinejmenším je třeba poznamenat, že tento příkaz je zastaralý - z dobrého důvodu. Buďte také opatrní, abyste SET FMTONLY OFF;
až budete hotovi, nebo se budete divit, proč jste úspěšně vytvořili uloženou proceduru, ale pak ji nemůžete spustit. A ne, nevaruji tě před tím, protože se mi to právě stalo. Upřímný. :-)
OPENQUERY
Vytvořením serveru propojeného se zpětnou smyčkou pak můžete použít nástroje jako OPENQUERY
spustit uloženou proceduru, ale vrátit sestavitelnou sadu výsledků (dobře, přijměte to jako extrémně volnou definici), kterou můžete zkontrolovat. Nejprve vytvořte server zpětné smyčky (to předpokládá místní instanci s názvem FOO
):
USE master;
GO
EXEC sp_addlinkedserver @server = N'.\FOO', @srvproduct=N'SQL Server'
GO
EXEC sp_serveroption @server=N'.\FOO', @optname=N'data access',
@optvalue=N'true';
Nyní můžeme použít výše uvedený postup a vložit jej do dotazu, jako je tento:
SELECT * INTO #t
FROM OPENQUERY([.\FOO], 'EXEC dbname.dbo.bar;')
WHERE 1 = 0;
SELECT c.name, t.name
FROM tempdb.sys.columns AS c
INNER JOIN sys.types AS t
ON c.system_type_id = t.system_type_id
WHERE c.[object_id] = OBJECT_ID('tempdb..#t');
Toto ignoruje typy aliasů (dříve známé jako uživatelsky definované datové typy) a také může zobrazit dva řádky pro sloupce definované jako například sysname
. Ale z výše uvedeného produkuje:
name name
---- --------
b int
c datetime
a varchar
Je zřejmé, že je zde ještě více práce - varchar
nezobrazuje délku a u jiných typů, jako je datetime2
, budete muset získat přesnost / měřítko , time
a decimal
. Ale to je začátek.
SQL Server 2012
V SQL Server 2012 jsou některé nové funkce, které výrazně usnadňují zjišťování metadat. Pro výše uvedený postup můžeme provést následující:
SELECT name, system_type_name
FROM sys.dm_exec_describe_first_result_set_for_object
(
OBJECT_ID('dbo.bar'),
NULL
);
Mimo jiné to ve skutečnosti poskytuje přesnost a měřítko a řeší za nás typy aliasů. Pro výše uvedený postup to dává:
name system_type_name
---- ----------------
a varchar(1)
b int
c datetime
Vizuálně se moc neliší, ale když se s různou přesností a měřítkem začnete zabývat všemi různými typy dat, oceníte práci navíc, kterou za vás tato funkce udělá.
Nevýhoda:V SQL Server 2012 alespoň tyto funkce fungují pouze pro první resultset (jak název funkce napovídá).