我想在不使用游标或循环的情况下为表的每一行执行存储过程。 让我们说我的表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为所有名称执行存储过程?
答案 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)
EXEC
@Query
()