如何在select内使用存储过程?

时间:2019-01-28 16:00:21

标签: sql sql-server tsql

我不是开发人员,所以我很抱歉这个问题。我是一名只有BASH脚本背景知识的系统管理员。

我正在尝试完成以下任务:

1)从一些SQL Server DMV中选择一些列

2)在以前的输出中添加一个名为“ OperState”的列

3)此“ OperState”列必须是步骤1中特定SELECTED列的存储过程的输出(在shell中,它类似于while读取var; do; $ OperState = some command ; echo $ var1 $ var2 ... $ OperState)

想法是1)使用此tsql列出我所有的链接服务器:

SELECT ss.server_id 
          ,ss.name 
          ,'Server ' = Case ss.Server_id 
                            when 0 then 'Current Server' 
                            else 'Remote Server' 
                            end 
          ,ss.product 
          ,ss.provider 
          ,ss.catalog 
          ,'Local Login ' = case sl.uses_self_credential 
                            when 1 then 'Uses Self Credentials' 
                            else ssp.name 
                            end 
           ,'Remote Login Name' = sl.remote_name 
           ,'RPC Out Enabled'    = case ss.is_rpc_out_enabled 
                                   when 1 then 'True' 
                                   else 'False' 
                                   end 
           ,'Data Access Enabled' = case ss.is_data_access_enabled 
                                    when 1 then 'True' 
                                    else 'False' 
                                    end 
           ,ss.modify_date 
      FROM sys.Servers ss 
 LEFT JOIN sys.linked_logins sl 
        ON ss.server_id = sl.server_id 
 LEFT JOIN sys.server_principals ssp 
        ON ssp.principal_id = sl.local_principal_id

并添加2)名为“ OperState”的附加列,在该列中,我将执行以下其他tsql 3)为先前选择的每个“ ss.name”:

 declare @srvr nvarchar(128), @retval int;
 set @srvr = 'my_linked_srvr';
 begin try
    exec @retval = sys.sp_testlinkedserver @srvr;
 end try
 begin catch
    set @retval = sign(@@error);
 end catch;
 if @retval <> 0
  raiserror('Unable to connect to server. This operation will be tried later!', 16, 2 );

我知道我可以在执行循环中使用游标,但是我不知道如何正确地将第一个选择中的变量重用到循环中,以及如何从该循环中产生新的输出到新的列中。

1 个答案:

答案 0 :(得分:0)

您不能从查询内部调用存储过程。

您将需要一个游标,一个临时表和一些奇特的错误处理,因此这是TSQL编程的重要内容。

类似这样的东西:

create or alter procedure TestLinkedServers
as
begin
/*
exec TestLinkedServers
*/

    set nocount on;

    SELECT  ss.server_id 
            ,ss.name 
            ,'Server ' = Case ss.Server_id 
                            when 0 then 'Current Server' 
                            else 'Remote Server' 
                            end 
            ,ss.product 
            ,ss.provider 
            ,ss.catalog 
            ,'Local Login ' = case sl.uses_self_credential 
                            when 1 then 'Uses Self Credentials' 
                            else ssp.name 
                            end 
            ,'Remote Login Name' = sl.remote_name 
            ,'RPC Out Enabled'    = case ss.is_rpc_out_enabled 
                                    when 1 then 'True' 
                                    else 'False' 
                                    end 
            ,'Data Access Enabled' = case ss.is_data_access_enabled 
                                    when 1 then 'True' 
                                    else 'False' 
                                    end 
            ,ss.modify_date
            , cast(null as bit) OperState
            , cast(null as nvarchar(2000)) StateMessage
    into #linkedServers
          FROM sys.Servers ss 
     LEFT JOIN sys.linked_logins sl 
            ON ss.server_id = sl.server_id 
     LEFT JOIN sys.server_principals ssp 
            ON ssp.principal_id = sl.local_principal_id

    declare c cursor local for
    select name from #linkedServers
    for update of OperState, StateMessage

    declare @name sysname
    open c
    fetch next from c into @name
    while @@FETCH_STATUS = 0
    begin
         declare @retval int = 1;
         declare @em nvarchar(2000) = null;

         begin try
            exec sys.sp_testlinkedserver @name;
         end try
         begin catch
             set @em = error_message();
             set @retval = 0;
         end catch;

         update #linkedServers set OperState = @retval, StateMessage = @em
         where current of c

         fetch next from c into @name
    end
    close c
    deallocate c

    select * from #linkedServers
end