Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Извличане на дефиниция на колона за набор от резултати от запомнени процедури

Така че да кажем, че имате съхранена процедура в tempdb:

USE tempdb;
GO

CREATE PROCEDURE dbo.my_procedure
AS
BEGIN
    SET NOCOUNT ON;

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

Има доста сложен начин, по който можете да определите метаданните, които съхранената процедура ще изведе. Има няколко предупреждения, включително процедурата може да изведе само един набор от резултати и че ще бъде направено най-добро предположение за типа данни, ако не може да бъде определен точно. Това изисква използването на OPENQUERY и свързан сървър с обратна връзка с 'DATA ACCESS' свойството е зададено на true. Можете да проверите sys.servers, за да видите дали вече имате валиден сървър, но нека просто създадем такъв ръчно наречен loopback :

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

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

Сега, когато можете да заявите това като свързан сървър, можете да използвате резултата от всяка заявка (включително извикване на съхранена процедура) като обикновен SELECT . Така че можете да направите това (обърнете внимание, че префиксът на базата данни е важно, в противен случай ще получите грешка 11529 и 2812):

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

Ако можем да изпълним SELECT * , можем също да извършим SELECT * INTO :

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

И след като тази таблица #tmp съществува, можем да определим метаданните, като кажем (ако приемем SQL Server 2005 или по-нова):

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

(Ако използвате SQL Server 2000, можете да направите нещо подобно с syscolumns, но нямам удобен екземпляр 2000 за валидиране на еквивалентна заявка.)

Резултати:

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

В Денали това ще бъде много, много, много по-лесно. Отново все още има ограничение на първия набор от резултати, но не е нужно да настройвате свързан сървър и да прескачате през всички тези обръчи. Можете просто да кажете:

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

Резултати:

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

До Denali, предлагам да бъде по-лесно просто да запретнете ръкави и да разберете типовете данни сами. Не само защото е досадно да преминавате през горните стъпки, но и защото е много по-вероятно да направите правилно (или поне по-точно) предположение, отколкото двигателят, тъй като типът данни предполага, че двигателят прави, ще се основава на времето на изпълнение изход, без никакви външни познания за областта на възможните стойности. Този фактор ще остане верен и в Denali, така че не оставайте с впечатлението, че новите функции за откриване на метаданни са крайни, те просто правят горното малко по-малко досадно.

О, и за някои други потенциални проблеми с OPENQUERY , вижте статията на Erland Sommarskog тук:

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. Урок за SQL Server – Всичко, от което се нуждаете, за да овладеете Transact-SQL

  2. SQL Server LIKE, съдържащ символи в скоби

  3. Как да намерите съпоставянето в SQL Server (T-SQL)

  4. Съхраняване на съобщението за рейзрор на SqlServer в C#

  5. Как да изберете данни на таблица от друга база данни в SQL Server?