【问题标题】:Use the result of a system stored procedure as a queryable table将系统存储过程的结果用作可查询表
【发布时间】:2014-06-13 03:07:34
【问题描述】:

注意:最高linked question 并不能解决系统存储过程的问题,但已经接近了。在评论者的帮助下,I came to a working answer

尝试对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 的临时表或表变量?或者:是否存在比每次都预定义完整表更紧凑的表达式?

(顺便说一句,题外话,Googling for the exact term SELECT * INTO #tmp exec sp_spaceused 在撰写本文时,只返回了一个结果)

【问题讨论】:

标签: sql-server tsql stored-procedures table-variable


【解决方案1】:

我们不能在存储过程中使用SELECT,这就是SELECT * INTO ..Exec sp_ 不起作用的原因。

要获得从存储过程返回的结果集,我们可以INSERT INTO 一个表。

SELECT INTO 语句动态创建表并从源表/视图/函数中插入数据。唯一的条件是源表应该存在并且您应该能够从中选择。

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

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

INSERT INTO #TempTable
EXECUTE sp_Proc

【讨论】:

  • 您说“您需要先创建表”。确实,但这正是我的问题的重点。我不想这样做,对于系统 sp,这可能非常乏味,尤其是。用于临时查询。
【解决方案2】:

TL;DR:使用 SET FMTONLY OFFOPENQUERY,详情如下。

看来that the link provided by Daniel E. 只是解决方案的一部分。例如,如果您尝试:

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

您将收到以下错误:

链接服务器“LOCALSERVER\SQL2008”的 OLE DB 提供程序“SQLNCLI10”为列提供了不一致的元数据。名称在执行时已更改。

我找到了解决方案through this postthen a blog-post on OPENQUERY,这反过来又告诉我,在SQL2008之前,你需要使用SET FMTONLY OFF。最终的解决方案,本质上非常简单(并且更容易完成,因为不需要指定环回链接服务器),是这样的:

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

另外,如果你没有设置DATA-ACCESS,你可能会得到如下错误:

没有为数据访问配置服务器“SERVERNAME\SQL2008”。

这可以通过运行以下命令来解决:

EXEC sp_serveroption 'SERVERNAME\SQL2008', 'DATA ACCESS', TRUE

【讨论】:

  • 我需要的只是 SET FMTONLY OFF;添加到我的声明中。我认为我的连接保留了以前 OPENROWSET 命令的设置。感谢您指出了这一点!这在当时并不明显。
【解决方案3】:
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. :)

【讨论】:

  • 欢迎来到 SO。建议为答案提供上下文,而不仅仅是复制代码的 sn-p。感谢您的努力,但它没有回答问题,您的代码将在数据库中创建一个新的实际表,这不是我最初的问题所问的(相反,它试图阻止这种情况)。具体来说,我写道:“是否存在比每次都必须预定义完整表更紧凑的表达式” ...也许我没有抓住重点,但是,请编辑您的答案以澄清。
猜你喜欢
  • 2010-10-10
  • 1970-01-01
  • 1970-01-01
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多