使用字符串变量为表的每一行执行存储过程

时间:2018-05-25 09:43:39

标签: sql sql-server tsql stored-procedures

我想在不使用游标或循环的情况下为表的每一行执行存储过程。 让我们说我的表dbo.User包含以下用户的名称:

create table dbo.test_User  ( 
 Name varchar(50) )

insert into dbo.test_User  
   values  ('Deepanshu'),('IronMan'),('DoctorStrange')

我创建了一个只显示用户名的存储过程(虽然我真正的存储过程必须做很多事情)

create procedure dbo.usp_TestSP ( @name varchar(50) )
as
BEGIN
    select @name
END

现在我希望存储过程可以运行所有名称,如:

EXEC dbo.usp_TestSP 'Deepanshu';
EXEC dbo.usp_TestSP 'IronMan';
EXEC dbo.usp_TestSP 'DoctorStrange';

我创建了一个字符串变量@Query,它将存储我想要执行的t-sql查询

DECLARE @Query varchar(200);  
select @Query=STUFF(  
                    (select 'dbo.usp_TestSP '''+Name+''';' 
                     from dbo.test_user  
                     FOR XML PATH('')
                    ),1,0,''
                 )  
EXEC @Query

当我尝试执行此@Query时,它给出了一个错误说:

  

无法找到服务器' dbo'在sys.servers中。验证是否指定了正确的服务器名称。如有必要,执行存储过程sp_addlinkedserver以将服务器添加到sys.servers。

如何使用字符串变量@Query为所有名称执行存储过程?

1 个答案:

答案 0 :(得分:1)

您可以使用CURSOR通过存储过程调用来模拟FOR-EACH

DECLARE db_cursor CURSOR LOCAL FAST_FORWARD FOR 
SELECT *FROM  dbo.tesT_User;

DECLARE @name NVARCHAR(50);

OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO @name;

WHILE @@FETCH_STATUS = 0  
BEGIN  
      EXEC dbo.usp_TestSP @name = @name;

      FETCH NEXT FROM db_cursor INTO @name;
END 

CLOSE db_cursor;
DEALLOCATE db_cursor;

<强> DBFiddle Demo

警告:

如果它是简单的功能,那么CROSS/OUTER APPLY是一种方法。

SELECT *
FROM dbo.Test_User tu
OUTER APPLY (SELECT dbo.usp_TestSP(tu.name)) s(a);

<强> DBFiddle Demo2

修改

  

我想在没有光标或循环的情况下执行此操作,使用与上面显示的相同的逻辑

DECLARE @x NVARCHAR(MAX) = 
   (SELECT string_agg(FORMATMESSAGE('EXEC dbo.usp_TestSP @name=''%s'';', name)
   ,CHAR(13)) AS r FROM dbo.test_User);
PRINT @x;
EXEC(@x);

<强> DBFiddle Demo3

最后你的代码:

DECLARE @Query varchar(MAX);  
select @Query=STUFF((SELECT 'EXEC dbo.usp_TestSP @name=' +QUOTENAME(Name,'''') 
       + ';' from dbo.test_user
FOR XML PATH('')),1,0,'');
EXEC(@Query);

<强> DBFiddle Demo4

我做了什么:

  • 使用分号(;)这是非常好的做法
  • 将数据类型更改为VARCHAR(MAX)
  • 在SQL
  • 中添加了EXEC
  • 使用@Query
  • 包裹()