我有一个存储过程,它返回80列和300行。我要写一个select函数,它能得到2个这样的列。类似的
SELECT col1, col2 FROM EXEC MyStoredProc 'param1', 'param2'
当我使用上面的语法时,我得到了错误:
“无效的列名”。
我知道最简单的解决方案是更改存储过程,但我没有编写它,也不能更改它。
有什么办法能让我如愿以偿吗?
I could make a temp table to put the results in, but because there are 80 columns so I would need to make an 80 column temp table just to get 2 columns. I wanted to avoid tracking down all the columns that are returned.
I tried using WITH SprocResults AS .... as suggested by Mark, but I got 2 errors
Incorrect syntax near the keyword 'EXEC'.Incorrect syntax near ')'.
I tried declaring a table variable and I got the following error
Insert Error: Column name or number of supplied values does not match table definition
If I try
SELECT * FROM EXEC MyStoredProc 'param1', 'param2'
I get the error :
Incorrect syntax near the keyword 'exec'.
这适用于我:(即我只需要sp_help_job返回的30+的2列)
SELECT name, current_execution_status
FROM OPENQUERY (MYSERVER,
'EXEC msdb.dbo.sp_help_job @job_name = ''My Job'', @job_aspect = ''JOB''');
在这之前,我需要运行这个:
sp_serveroption 'MYSERVER', 'DATA ACCESS', TRUE;
....更新sys. xml文件。服务器表。(例如,在OPENQUERY中使用自引用默认情况下是禁用的。)
对于我的简单需求,我没有遇到Lance的出色链接的OPENQUERY部分中描述的任何问题。
Rossini,如果你需要动态地设置这些输入参数,那么OPENQUERY的使用就变得更加精细了:
DECLARE @innerSql varchar(1000);
DECLARE @outerSql varchar(1000);
-- Set up the original stored proc definition.
SET @innerSql =
'EXEC msdb.dbo.sp_help_job @job_name = '''+@param1+''', @job_aspect = N'''+@param2+'''' ;
-- Handle quotes.
SET @innerSql = REPLACE(@innerSql, '''', '''''');
-- Set up the OPENQUERY definition.
SET @outerSql =
'SELECT name, current_execution_status
FROM OPENQUERY (MYSERVER, ''' + @innerSql + ''');';
-- Execute.
EXEC (@outerSql);
我不确定使用sp_serveroption来更新现有的sys. exe之间的差异(如果有的话)。服务器直接自引用,而不是使用sp_addlinkedserver(如Lance的链接中所述)来创建副本/别名。
注1:
我更喜欢OPENQUERY而不是OPENROWSET,因为OPENQUERY不需要进程内的连接字符串定义。
注2:
说了这么多:通常我会使用INSERT…是的,这是额外的10分钟打字,但如果我能帮助它,我宁愿不跳:
(a)引用中引用,以及
(b)系统表,和/或狡猾的自引用链接服务器设置(即,对于这些,我需要向我们全能的dba辩护:)
但是在这个例子中,我不能使用INSERT…EXEC构造,因为sp_help_job已经使用了一个。(“INSERT EXEC语句不能嵌套。”)
正如问题中提到的,在执行存储过程之前很难定义80列的临时表。
另一种方法是根据存储过程结果集填充表。
SELECT * INTO #temp FROM OPENROWSET('SQLNCLI', 'Server=localhost;Trusted_Connection=yes;'
,'EXEC MyStoredProc')
如果您得到任何错误,您需要通过执行以下查询来启用特定的分布式查询。
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
要使用两个参数执行sp_configure以更改配置选项或运行RECONFIGURE语句,必须授予ALTER SETTINGS服务器级权限
现在可以从生成的表中选择特定的列
SELECT col1, col2
FROM #temp
我知道从sp执行和插入到临时表或表变量将是一个选项,但我不认为这是你的要求。根据您的要求,以下查询语句应该工作:
Declare @sql nvarchar(max)
Set @sql='SELECT col1, col2 FROM OPENROWSET(''SQLNCLI'', ''Server=(local);uid=test;pwd=test'',
''EXEC MyStoredProc ''''param1'''', ''''param2'''''')'
Exec(@sql)
如果你有可信连接,那么使用下面的查询语句:
Declare @sql nvarchar(max)
Set @sql='SELECT col1, col2 FROM OPENROWSET(''SQLNCLI'', ''Server=(local);Trusted_Connection=yes;'',
''EXEC MyStoredProc ''''param1'''', ''''param2'''''')'
Exec(@sql)
如果运行上面的语句出错,那么只需运行下面的语句:
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
我希望这将帮助那些将面临类似问题的人。如果有人想尝试temp表或表变量,应该如下所示,但在这种情况下,你应该知道sp返回多少列,然后你应该在temp表或表变量中创建这么多列:
--for table variable
Declare @t table(col1 col1Type, col2 col2Type)
insert into @t exec MyStoredProc 'param1', 'param2'
SELECT col1, col2 FROM @t
--for temp table
create table #t(col1 col1Type, col2 col2Type)
insert into #t exec MyStoredProc 'param1', 'param2'
SELECT col1, col2 FROM #t