sql server-将系统存储过程的结果用作可查询表



注意:最高链接问题不能解决系统存储过程的问题,但它很接近。在评论者的帮助下,我得到了一个有效的答案

尝试对sp_spaceused使用以下语句时,会引发错误

SELECT * INTO #tblOutput exec sp_spaceused 'Account'
SELECT * FROM #tblOutput 

错误:

必须指定要从中选择的表。

和:

对象或列名丢失或为空。对于SELECT INTO语句,请验证每列都有一个名称。对于其他语句,请查找空别名。不允许使用定义为"或[]的别名。将别名更改为有效名称。

当我完全声明一个表变量时,它按预期工作,所以在我看来,存储过程确实返回了一个实际的表。

CREATE TABLE  #tblOutput (
    name NVARCHAR(128) NOT NULL, 
    rows CHAR(11) NOT NULL, 
    reserved VARCHAR(18) NOT NULL,
    data VARCHAR(18) NOT NULL,
    index_size VARCHAR(18) NOT NULL,
    unused VARCHAR(18) NOT NULL)
INSERT INTO #tblOutput exec sp_spaceused 'Response'
SELECT * FROM #tblOutput

为什么不能使用结果集为EXECUTE sp_xxx的临时表或表变量?或者:是否存在比每次都要预定义完整表更紧凑的表达式?

(顺便说一句,在撰写本文时,在谷歌上搜索确切的术语SELECT * INTO #tmp exec sp_spaceused,只返回了一个结果)

TL;DR:使用SET FMTONLY OFFOPENQUERY,详细信息如下。

Daniel E.提供的链接似乎只是解决方案的一部分。例如,如果您尝试:

-- no need to use sp_addlinkedserver
-- must fully specify sp_, because default db is master
SELECT * FROM OPENQUERY(
   [SERVERNAMESQL2008], 
   'exec somedb.dbo.sp_spaceused ''Account''')

您将收到以下错误:

链接服务器"LOCALSERVER\SQL2008"的OLE DB访问接口"SQLNCLI10"为列提供了不一致的元数据。在执行时更改了名称

我通过这篇文章找到了解决方案,然后在OPENQUERY上发了一篇博客文章,告诉我在SQL2008之前,您需要使用SET FMTONLY OFF。最终的解决方案是:

SELECT * FROM OPENQUERY(
   [SERVERNAMESQL2008], 
   'SET FMTONLY OFF 
   EXEC somedb.dbo.sp_spaceused ''Account''')

此外,如果您没有设置DATA-ACCESS,则可能会出现以下错误:

服务器"SERVERNAME\SQL2008"未配置为数据访问

这可以通过运行以下命令来纠正:

EXEC sp_serveroption 'SERVERNAMESQL2008', 'DATA ACCESS', TRUE

我们无法从存储过程中SELECT,这就是SELECT * INTO ..Exec sp_无法工作的原因。

为了得到存储过程返回的结果集,我们可以INSERT INTO一个表。

SELECT INTO语句动态创建一个表,并插入源表/View/Function中的数据。唯一的条件是源表应该存在,并且您应该能够从中进行选择

Sql Server不允许您从sp_使用SELECT,因此在执行存储过程时只能使用INSERT INTO语句,这意味着在运行时,您可以将返回的结果集添加到表中,并在稍后阶段从该表中选择。

INSERT INTO语句需要目标表名"现有表"。因此,无论您使用Temp表、表变量还是Sql服务器持久表,都需要首先创建表,并且只有它们才能使用语法

INSERT INTO #TempTable
EXECUTE sp_Proc
Using [YOUR DATABASE NAME]
CREATE TABLE [YOURTABLENAME]
(Database_Name Varchar(128),
DataBase_Size VarChar(128),
unallocated_Space Varchar(128),
reserved Varchar(128),
data Varchar(128),
index_size Varchar(128),
unused Varchar(128)
);
INSERT INTO dbo.[YOUR TABLE NAME]
(
    Database_Name,
    DataBase_Size,
    unallocated_Space,
    reserved,
    data,
    index_size,
    unused
)
EXEC sp_spaceused @oneresultset = 1  
--To get it to return it all as one data set add the nonresultset=1 at the end and viola good to go for writing to a table. :)

最新更新