一个关于“OLE DB 提供程序 'sqloledb' 指出该对象中没有任何列”错误的解决方法

一个关于“OLE DB 提供程序 'sqloledb' 指出该对象中没有任何列”错误的解决方法

 

在网上看到一个网友提问把系统过程的结果输出到文本文件 ,心想这不简单呀,bcp+openrowset呀轻松解决呀,本着认真的态度(其实是怕写个错误的让人家笑话我)我在我的查询分析器里写个试:

--1

select * 

from

OPENROWSET('SQLOLEDB','SERVER=.;UID=sa;PWD=','exec csdn_test.dbo.sp_helpsrvrolemember') AS a

 

--2

SELECT *

FROM

 openrowset('sqloledb','Trusted_Connection=yes','exec csdn_test..sp_helpsrvrolemember ')

 

F5一运行,完了,出丑了

 

服务器: 消息 7357,级别 16,状态 2,行 1

未能处理对象 'exec csdn_test.dbo.sp_helpsrvrolemember'OLE DB 提供程序 'SQLOLEDB' 指出该对象中没有任何列。

OLE DB 错误跟踪[Non-interface error:  OLE DB provider unable to process object, since the object has no columnsProviderName='SQLOLEDB', Query=exec csdn_test.dbo.sp_helpsrvrolemember']。

 

这老写的语法怎么会报错呢,自己写一个过程试试,一试更呆了

 

create proc pr_test

as

begin

    select * from tb

end

go

 

 

SELECT   *  

FROM   openrowset('sqloledb',   'Trusted_Connection=yes','exec csdn_test..pr_test')

 

drop proc pr_test

/*

TypeID      Type

----------- ----

1           t1

2           t2

3           t3

4           t4

 

(所影响的行数为 4 行)

*/

 

结果是想的,那为什么这个系统过程不行呢?那先看看这个过程是什么东东:

 

sp_helptext 'master..sp_helpsrvrolemember'

 

/*

Text                                                                                                                                                                                                                                                            

------------------------------------------

CREATE PROCEDURE sp_helpsrvrolemember

    @srvrolename       sysname = NULL

AS

    if @srvrolename is not null

    begin

        -- VALIDATE GIVEN NAME

        if not exists (select * from master.dbo.spt_values

              where name = @srvrolename and low = 0 and type = 'SRV')

        begin

           raiserror(15412, -1, -1, @srvrolename)

           return (1)

        end

 

        -- RESULT SET FOR SINGLE SERVER-ROLE

        select 'ServerRole' = spv.name, 'MemberName' = lgn.name, 'MemberSID' = lgn.sid

           from master.dbo.spt_values spv, master.dbo.sysxlogins lgn

           where spv.name = @srvrolename and

                spv.low = 0 and

                spv.type = 'SRV' and

                lgn.srvid IS NULL and

                spv.number & lgn.xstatus = spv.number

    end

    else

    begin

        -- RESULT SET FOR ALL SERVER-ROLES

        select 'ServerRole' = spv.name, 'MemberName' = lgn.name, 'MemberSID' = lgn.sid

           from master.dbo.spt_values spv, master.dbo.sysxlogins lgn

           where spv.low = 0 and

                spv.type = 'SRV' and

                lgn.srvid IS NULL and

                spv.number & lgn.xstatus = spv.number

    end

 

    return (0) -- sp_helpsrvrolemember

 

*/

 

 

一看,哦,难道这个结果因为输入参数不同而有不同select来返回影响了?或是为空时raiserror 没有select 结果集吗?好办,我们再试:

 

create proc pr_test

@p int =null

as

begin

    if @p is  null

        select * from tb

    else

        return 0

    return 1

 

end

go

 

create proc pr_test1

@p int =null

as

begin

    if @p is not null

        return 0

    else

        select * from tb

    return 1

 

end

go

 

create proc pr_test2

@p int =null

as

begin

    if @p is not null

        return 0

    else

        select * from tb

    return 1

 

end

go

 

SELECT   *  

FROM   openrowset('sqloledb',   'Trusted_Connection=yes','exec csdn_test..pr_test')

 

SELECT   *  

FROM   openrowset('sqloledb',   'Trusted_Connection=yes','exec csdn_test..pr_test 1')

 

SELECT   *  

FROM   openrowset('sqloledb',   'Trusted_Connection=yes','exec csdn_test..pr_test1')

 

SELECT   *  

FROM   openrowset('sqloledb',   'Trusted_Connection=yes','exec csdn_test..pr_test2')

 

 

drop proc pr_test,pr_test1,pr_test2

 

通过以上的测试,结果很明显了,也就是查询语句对过程可能的结果集进行了分析,特别第一个过程带参与不带参的结果就很明显了,上网一gg,问的人还真不少,好多人期待2005进行改进,难道2000就真的不行了?,通过查sql2000的联机帮助,发现这个设置项,很管用,哈哈

 

SET FMTONLY

只将元数据返回给客户端。

语法

SET FMTONLY { ON | OFF }

注释

SET FMTONLY 为 ON 时,将不对行进行处理,也不将行作为请求的结果发送到客户端。

SET FMTONLY 的设置是在执行或运行时设置,而不是在分析时设置。

 

很显然,这个开关项正是我们所想要分析器应该执行的结果,好试一下吧:

 

 

select * 

from

    OPENROWSET('SQLOLEDB','DRIVER={SQL Server};SERVER=.;UID=sa;PWD=','set fmtonly off;exec csdn_test.dbo.sp_helpsrvrolemember') AS a

 

 

select * 

from

    OPENROWSET('SQLOLEDB','SERVER=.;UID=sa;PWD=','set fmtonly off;exec csdn_test.dbo.sp_helpsrvrolemember') AS a

 

 

exec master..xp_cmdshell

'bcp "select * from OPENROWSET(''SQLOLEDB'',''SERVER=.;UID=sa;PWD='',''set fmtonly off;exec csdn_test.dbo.sp_helpsrvrolemember'') AS a " queryout c:/Authors.txt -c -S. -Usa -P'

 

/*

ServerRole                          MemberName                                                                            MemberSID

----------------------------------- ------------------- ------

sysadmin BUILTIN/Administrators 0x01020000000000052000000020020000

sysadmin sa                         0x01

 

(所影响的行数为 2 行)

 

ServerRole             MemberName             MemberSID

--------------------- ----------- ---------------------------

sysadmin BUILTIN/Administrators 0x01020000000000052000000020020000

sysadmin sa                         0x01

 

(所影响的行数为 2 行)

 

output                                                                                                                                                                                                                                                          

-------------------

NULL

开始复制...

NULL

已复制了 2 行。

数据包的大小(字节): 4096

时钟时间(毫秒):      10

NULL

 

(所影响的行数为 7 行)

 

*/

 

 

 

sql2005内确实进行了改进,下面 二种写法都可以得到结果:

 

 

select * 

from

    openrowset('SQLNCLI','Server=./sql2005;Trusted_Connection=yes','exec testcsdn..sp_helpsrvrolemember')as a

select * 

from

    OPENROWSET('SQLOLEDB','DRIVER={SQL Server};SERVER=./sql2005;UID=sa;PWD=flystone','exec testcsdn.dbo.sp_helpsrvrolemember') AS a

 

 

 

 

 

 

你可能感兴趣的:(MSSQL)