求助: sp_oacreate 和sp_oadestroy 让我很困惑

律己修心 2008-07-09 11:57:05
说明一下情况:

我想用动态语句的查询结果输出到EXCEL中的动态Sheet中
于是拜读了邹老大的文章,得到了很大的提示
(文章:http://topic.csdn.net/u/20080515/17/a97870aa-0a43-4f6c-b8cf-9c9ece0d9b09.html)

但是,我在运行邹老大的存储过程时出现了障碍
把关键的地方整理了一下
希望大家帮忙解决一下

下面是动态生成xls文件的一部分(写的比较粗糙,大家凑和着看吧哈哈)

declare	@hr int,@obj int,@constr varchar(4000),@out int,
@sql varchar(2000),@tb varchar(200),@path varchar(200)

--创建一个adodb的连接(OLE对象)
exec @hr=sp_oacreate 'adodb.connection',@obj out
if @hr<>0 raiserror('1error',16,1)

--调用adodb的方法open
set @path='D:\test.xls'
set @constr='Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties="Excel 8.0;HDR=YES;DATABASE='+@path+'"'
exec @hr=sp_oamethod @obj,'open',null,@constr
if @hr<>0 raiserror('2error',16,1)

--调用adodb的方法execute 到这步时,xls文件就已经生成了
set @tb ='ta'
set @sql='create table ta (a int)'
exec @hr=sp_oamethod @obj,'execute',@out out,@sql

--释放上面已创建的 OLE 对象adodb
--问题就出在这里,感觉sp_oadestroy这段代码似乎没有起作用,并没有释放OLE对象
exec @hr=sp_oadestroy @obj
if @hr<>0 raiserror('3error',16,1)


--用静态SQL实现的话,提示找不到对象ta$,请确认路径和文件名的正确性(所以只能用动态的去实现)
insert into
openrowset('microsoft.jet.oledb.4.0','excel 8.0;hdr=yes;database=D:\test.xls','select * from [ta$]')(a)
select * from csdn.dbo.ta

--用动态SQL实现的话,提示文件‘’不能打开,正在被其它的用户打开,没有读取的权限(估计是没有释放OLE对象)
set @sql='insert into
openrowset(''microsoft.jet.oledb.4.0'',''excel 8.0;hdr=yes;database='+@path+''',''select * from ['+@tb+'$]'')(a)
select * from csdn.dbo.ta'
exec (@sql)


请有经验的朋友帮忙看看
给点思路
不胜感激
谢谢了
...全文
528 25 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
overtime4 2011-04-06
  • 打赏
  • 举报
回复
学习一下。
律己修心 2008-07-09
  • 打赏
  • 举报
回复
to:SF

D:\test.xls

服务器就是我的本机啊
是在本地进行的
昵称被占用了 2008-07-09
  • 打赏
  • 举报
回复
这里的D:\test.xls指的是服务器的D盘,不是客户端的
律己修心 2008-07-09
  • 打赏
  • 举报
回复
谢谢二位的帮助

wgzaaa 2008-07-09
  • 打赏
  • 举报
回复
完美行动,没有问题,我只是想弄清静态的为什么不行。
现在我也明白了,因为用静态语句,需要预编,此过程中excel还没有创建,是编译不过报错,所以不能用静态语句。
nzperfect 2008-07-09
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 wgzaaa 的回复:]
去掉静态的我也试过可行,
但exec @hr=sp_oadestroy @obj 没有达到目的,去了这句结果是一样的
那是因为动态的自动分隔了批,对象自动释放了。
[/Quote]

现在我不太明白你执行有什么问题?
我现在怎么执行都是正确的。
wgzaaa 2008-07-09
  • 打赏
  • 举报
回复
去掉静态的我也试过可行,
但exec @hr=sp_oadestroy @obj 没有达到目的,去了这句结果是一样的
那是因为动态的自动分隔了批,对象自动释放了。
nzperfect 2008-07-09
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 wgzaaa 的回复:]
是有问题,刚才我是分步执行的,按14楼好象还是不行
[/Quote]
我刚才弄错了,
我又这样试了下,没有问题:

declare    @hr int,@obj int,@constr varchar(4000),@out int,
@sql varchar(2000),@tb varchar(200),@path varchar(200)

--创建一个adodb的连接(OLE对象)
exec @hr=sp_oacreate 'adodb.connection',@obj out
if @hr<>0 raiserror('1error',16,1)

--调用adodb的方法open
set @path='D:\test.xls'
set @constr='Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties="Excel 8.0;HDR=YES;DATABASE='+@path+'"'
exec @hr=sp_oamethod @obj,'open',null,@constr
if @hr<>0 raiserror('2error',16,1)

--调用adodb的方法execute 到这步时,xls文件就已经生成了
set @tb ='ta'
set @sql='create table ta (a int)'
exec @hr=sp_oamethod @obj,'execute',@out out,@sql

--释放上面已创建的 OLE 对象adodb
--问题就出在这里,感觉sp_oadestroy这段代码似乎没有起作用,并没有释放OLE对象
exec @hr=sp_oadestroy @obj
if @hr<>0 raiserror('3error',16,1)


--用动态SQL实现的话,提示文件‘’不能打开,正在被其它的用户打开,没有读取的权限(估计是没有释放OLE对象)
set @sql='insert into
openrowset(''microsoft.jet.oledb.4.0'',''excel 8.0;hdr=yes;database='+@path+''',''select * from ['+@tb+'$]'')(a)
select a from dbname.dbo.tb'
exec (@sql)
wgzaaa 2008-07-09
  • 打赏
  • 举报
回复
是有问题,刚才我是分步执行的,按14楼好象还是不行
律己修心 2008-07-09
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 hery2002 的回复:]
你用什么账户连的,
看看当前的账户有没有D:\的读取权限.
[/Quote]

用SA连的
数据库是我自己装的
律己修心 2008-07-09
  • 打赏
  • 举报
回复
朋友们

成功了

但是我更郁闷了

又换了一台别人的机器就成功了

而我的机器不行,我却还不知道原因

55555555555555555555555555555555哗哗的
hery2002 2008-07-09
  • 打赏
  • 举报
回复
你用什么账户连的,
看看当前的账户有没有D:\的读取权限.
律己修心 2008-07-09
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 perfectaction 的回复:]
单独建表 ta,一个列a int.
然后去掉:

SQL code--调用adodb的方法execute 到这步时,xls文件就已经生成了
set @tb ='ta'
set @sql='create table ta (a int)'
exec @hr=sp_oamethod @obj,'execute',@out out,@sql


这段,就可以直行了。
[/Quote]

我不太理解

不过这个ta表指的是D:\test.xls文件中的一个sheet名 a是一个表格


我换个机器执行了一下
结果在第二步就报错了
文件‘’不能打开,正在被其它的用户打开,没有读取的权限

看来和权限有很大关系
难解决啊
nzperfect 2008-07-09
  • 打赏
  • 举报
回复
单独建表 ta,一个列a int.
然后去掉:
--调用adodb的方法execute 到这步时,xls文件就已经生成了
set @tb ='ta'
set @sql='create table ta (a int)'
exec @hr=sp_oamethod @obj,'execute',@out out,@sql

这段,就可以直行了。
nzperfect 2008-07-09
  • 打赏
  • 举报
回复
--调用adodb的方法execute 到这步时,xls文件就已经生成了
set @tb ='ta'
set @sql='create table ta (a int)'
exec @hr=sp_oamethod @obj,'execute',@out out,@sql

我觉得这个地方有问题吧。
wgzaaa 2008-07-09
  • 打赏
  • 举报
回复
还以为7楼不是楼主,xx.dbo.ta是 数据库名+用户史+表名 改成 ta 就可以,并建一表
create tableta(a int)
insert into ta select 1
律己修心 2008-07-09
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 wgzaaa 的回复:]
代码没有问题,我机器能执行(改了7楼说的库名),一时也没模拟出楼主的问题
建议先删除D盘中test.xls、文件后重启机器后再执行一下,还要保证csdn.dbo.ta存在并且只有一个字段
[/Quote]


谢谢

我用别人机器试一下
律己修心 2008-07-09
  • 打赏
  • 举报
回复
表结果就是一个字段a int
wgzaaa 2008-07-09
  • 打赏
  • 举报
回复
代码没有问题,我机器能执行(改了7楼说的库名),一时也没模拟出楼主的问题
建议先删除D盘中test.xls、文件后重启机器后再执行一下,还要保证csdn.dbo.ta存在并且只有一个字段
律己修心 2008-07-09
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 perfectaction 的回复:]
我试了下,执行到
insert into
openrowset('microsoft.jet.oledb.4.0','excel 8.0;hdr=yes;database=D:\test.xls','select * from [ta$]')(a)
select * from xx.dbo.ta
时报,找不到xx.dbo.ta这个对象.
[/Quote]

create table xx.dbo.ta( a int)
insert into ta select 1
加载更多回复(5)
DECLARE @Object int; DECLARE @HR int; DECLARE @Property nvarchar(255); DECLARE @Return nvarchar(255); DECLARE @Source nvarchar(255), @Desc nvarchar(255); DECLARE @httpStatus int; DECLARE @response varchar(8000); --创建 OLE 对象的实例 EXEC @HR = sp_OACreate N'MSXML2.XMLHTTP.6.0',@Object OUT; IF @HR 0 BEGIN EXEC sp_OAGetErrorInfo @Object,@Source OUT,@Desc OUT; RAISERROR('Error Creating COM Component 0x%x, %s, %s',16,1, @HR, @Source, @Desc) GOTO END_ROUTINE END BEGIN --Open EXEC @HR = sp_OAMethod @Object,N'open',Null,'GET','http://localhost:1728/HttpServer/submit.aspx',FALSE; IF @HR 0 BEGIN EXEC sp_OAGetErrorInfo @Object,@Source OUT,@Desc OUT; RAISERROR('Open 0x%x, %s, %s',16,1, @HR, @Source, @Desc) GOTO CLEANUP END --setRequestHeader EXEC @HR = sp_OAMethod @Object,N'setRequestHeader',Null,'Content-Type','text/xml'; IF @HR 0 BEGIN EXEC sp_OAGetErrorInfo @Object,@Source OUT,@Desc OUT; RAISERROR('setRequestHeader 0x%x, %s, %s',16,1, @HR, @Source, @Desc) GOTO CLEANUP END --send EXEC @HR = sp_OAMethod @Object,N'send',Null,''; IF @HR 0 BEGIN EXEC sp_OAGetErrorInfo @Object,@Source OUT,@Desc OUT; RAISERROR('send 0x%x, %s, %s',16,1, @HR, @Source, @Desc) GOTO CLEANUP END --readyState EXEC @HR = sp_OAGetProperty @Object,'readyState', @httpStatus OUT; IF @HR 0 BEGIN EXEC sp_OAGetErrorInfo @Object,@Source OUT,@Desc OUT; RAISERROR('readyState 0x%x, %s, %s',16,1, @HR, @Source, @Desc) GOTO CLEANUP END --verify status IF @httpStatus 4 BEGIN RAISERROR('readyState http status bad', 16,1) GOTO CLEANUP END --status EXEC @HR = sp_OAGetProperty @Object,'status', @httpStatus OUT; IF @HR 0 BEGIN EXEC sp_OAGetErrorInfo @Object,@Source OUT,@Desc OUT; RAISERROR('getstatus 0x%x, %s, %s',16,1, @HR, @Source, @Desc) GOTO CLEANUP END --verify status IF @httpStatus 200 BEGIN Print Cast(@httpStatus As varchar) RAISERROR('Open http status bad', 16,1) GOTO CLEANUP END --responseText EXEC @HR = sp_OAGetProperty @Object, 'responseText', @response OUT IF @HR 0 BEGIN EXEC sp_OAGetErrorInfo @Object,@Source OUT,@Desc OUT; RAISERROR('responseText 0x%x, %s, %s',16,1, @HR, @Source, @Desc) GOTO CLEANUP END Print @response END CLEANUP: BEGIN EXEC @HR = sp_OADestroy @Object; IF @HR 0 BEGIN EXEC sp_OAGetErrorInfo @Object,@Source OUT,@Desc OUT; SELECT HR = convert(varbinary(4),@HR),Source=@Source,Description=@Desc; END END END_ROUTINE: RETURN; GO

34,871

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧