考虑以下存储过程:
create procedure [dbo].[MyTest] ( @p_SqlStatement nvarchar(max) )
as
begin
exec sp_executesql @p_SqlStatement
if @@ROWCOUNT = 1
begin
select 1;
end
else if @@ROWCOUNT <> 1
begin
select 0;
end
end
此存储过程当前返回2个数据集,一个包含exec sp_executesql @p_SqlStatement
数据,另一个数据集为1或0.有没有办法抑制第一个数据集?我的意思是,这个存储过程是否可能只返回1或0?
我尝试在RAISERROR( 'MyError', 18, 1 )
之后添加exec sp_executesql @p_SqlStatement
,然后在catch块中选择其他内容,但第一个结果集总是返回给我的存储过程调用者...
答案 0 :(得分:2)
您可以将查询嵌入if exists(
。
alter procedure [dbo].[MyTest] ( @p_SqlStatement nvarchar(max) )
as
begin
set @p_SqlStatement = 'if exists('+@p_SqlStatement+') select 1 else select 0'
exec sp_executesql @p_SqlStatement
end
但是有一些问题会导致无法飞行。
;
可能会有更多,但这些是我现在能想到的。
<强>更新强>
您可以尝试使用openrowset。
alter procedure [dbo].[MyTest] ( @p_SqlStatement nvarchar(max) )
as
begin
declare @S nvarchar(max)
set @S =
'if exists(
select *
from openrowset(
''SQLNCLI'',
''Server=localhost;Trusted_Connection=yes;'',
'+quotename(@p_SqlStatement, '''')+'
) as T
)
select 1
else
select 0'
exec (@S)
end
我从来没有在制作过程中使用过这个,但是从我做的测试来看,它看起来应该适用于SP,CTE和多行。
答案 1 :(得分:0)
您可以尝试使用NOCOUNT语句(http://msdn.microsoft.com/en-us/library/ms189837.aspx)
create procedure [dbo].[MyTest] ( @p_SqlStatement nvarchar(max) )
as
begin
SET NOCOUNT ON;
exec sp_executesql @p_SqlStatement
if @@ROWCOUNT = 1
begin
select 1;
end
else if @@ROWCOUNT <> 1
begin
select 0;
end
SET NOCOUNT OFF;
end
答案 2 :(得分:0)
尝试这种方法:
declare @mycount bigint
exec sp_executesql N'select @mycount = count(name) from Page where name like ''P%''', N'@mycount bigint OUTPUT', @mycount OUTPUT
select @mycount
您的语句@p_SqlStatement包含计数非常重要。
如果不是这种情况,意味着你想为你遇到的任何SQL运行这个sp,那么这没有用。我认为你无法抑制sp_executesql的输出。
编辑:你也可以试试这个:
declare @mycount bigint
exec sp_executesql N'SELECT * INTO ##MyTempTable from Page where name like ''P%'''
select count(*) from ##MyTempTable
drop table ##MyTempTable
这意味着您必须将以下内容添加到每个查询中(不知道这是否适用于sp?)“SELECT * INTO ## MyTempTable FROM” - 这应该不会很难。
“## temptables”是全局范围的临时表。这意味着它们也可以在sp_executesql sp之外使用。您必须明确删除该表。
答案 3 :(得分:0)
除了使用建议的OPENROWSET之外,我找不到任何其他解决方法。但是,我发现了一种与servername / instance无关的方法。我仍然需要重新配置服务器以接受临时分布式查询。这是最终结果:
create procedure [dbo].[MyTest] ( @p_SqlStatement nvarchar(max) )
as
begin
declare @sql nvarchar(max) = N'SELECT * INTO ##TMP FROM OPENROWSET(''SQLOLEDB'',''Server=' + @@SERVERNAME + ';Trusted_Connection=Yes;'',''' + @p_SqlStatement + ''')';
exec sp_executesql @sql
if ( select COUNT(1) from ##TMP ) = 1
begin
select 1;
end
else
begin
select 0;
end
drop table ##TMP;
end
此解决方案有其局限性:
@sql
上使用sp_executesql
变量和OPENROWSET
,因为我无法以另一种方式在OPENROWSET
内使用变量,因此这会产生动态SQL在OPENROWSET
,这在性能方面非常糟糕。我使用以下脚本重新配置服务器:
sp_configure 'Ad Hoc Distributed Queries', 1;
RECONFIGURE;
GO