SQL SERVER 如何调用ORCALE存储过程

时间:2021-06-11 04:25:26
环境:
服务器A:orcale10g+windows2003
服务器B:SQL SERVER 2000 ,SP4 + windows2003
在服务器B和服务器A之间已建立链接,并能成功访问,链接服务器名称 HSHIS
通过 select * from openquery(hshis,'select * from 服务器A表') 能成功访问

需求如下:
(需要在服务器B也就是SQL server 2000中写一个存储过程去调用服务器A orcale10g 中的存储过程P_BSHRP_inpbilling,orcale中的存储过程入参和出参标记如下。)

P_BSHRP_inpbilling  --存储过程名字

inpno    in number , float --住院号(入参)
adviceno in number , float --医嘱组号(入参)
feeno    in number , float --记账项目序号(入参)
counts   decimal , float --记账数量(入参)
opr varchar2 string, --记费员
finish   out number , float --完后标志(出参)-1 失败 0 成功
errorinfo out varchar2 string--错误信息(出参)

16 个解决方案

#1


。。。这样也行吗

#2


C.   使用用于   Oracle   的   Microsoft   OLE   DB   提供程序 
此示例创建一台名为   LONDON   Mktg   的链接服务器,该服务器使用用于   Oracle   的   Microsoft   OLE   DB   提供程序,并且假设此   Oracle   数据库的   SQL*Net   别名为   MyServer。 

USE   master 
GO 
--   To   use   named   parameters: 
EXEC   sp_addlinkedserver 
      @server   =   'LONDON   Mktg ', 
      @srvproduct   =   'Oracle ', 
      @provider   =   'MSDAORA ', 
      @datasrc   =   'MyServer ' 
GO 
--   OR   to   use   no   named   parameters: 
USE   master 
GO 
EXEC   sp_addlinkedserver   
      'LONDON   Mktg ',   
      'Oracle ',   
      'MSDAORA ', 
      'MyServer ' 
GO 


exec( 'delete   from   openquery(oracle_link, ' 'select   *     from   tt   where   t= ' '+@v+ ') ') 

#4


回复:ws_hgo

你的这个方法是删除数据吧??我要的是一个存储过程,还有你个这是直接百度的吧?我早百度过N次了。不过还是谢谢

#5


http://blog.csdn.net/bugchen888/archive/2006/02/24/608152.aspx
这个网页前天我就百度到了,可是试了N次还是不行。好象有问题

#6


在ORCALE10G的 SQL*PLUS里执行下面语句能成功执行

declare 
finish float;
errorinfo varchar2(80);
begin
P_BSHRP_inpbilling(195303,19722918,13046,1,'01',finish,errorinfo); 
dbms_output.put_line(finish); 
dbms_output.put_line(errorinfo); 
end; 

#7


一个例子:

hr@ORCL> CREATE OR REPLACE PROCEDURE P_TEST(emp_id NUMBER) AS
  2      salary real;
  3    BEGIN
  4      SELECT salary INTO salary FROM employees WHERE employee_id = emp_id;
  5    END;
  6  /

过程已创建。

hr@ORCL> call p_test(100);

调用完成。

hr@ORCL> CREATE OR REPLACE PACKAGE test_pkg AS
  2  PROCEDURE TestProcedure
  3  (
  4      I_Parameter1 IN NUMBER,
  5      I_Parameter2 IN NUMBER,
  6      O_Parameter1 OUT NUMBER,
  7      O_Parameter2 OUT NUMBER
  8  );
  9  END;
 10  /

程序包已创建。

hr@ORCL> CREATE OR REPLACE PACKAGE BODY test_pkg AS
  2  PROCEDURE TestProcedure
  3  (
  4      I_Parameter1 IN NUMBER,
  5      I_Parameter2 IN NUMBER,
  6      O_Parameter1 OUT NUMBER,
  7      O_Parameter2 OUT NUMBER
  8  ) AS
  9  BEGIN
 10     O_Parameter1 := I_Parameter1 + 1;
 11     O_Parameter2 := I_Parameter2 + 1;
 12  END TestProcedure;
 13  END;
 14  /

程序包体已创建。

hr@ORCL> DESC TEST_PKG;
PROCEDURE TESTPROCEDURE
参数名称                       类型                    输入/输出默认值?
------------------------------ ----------------------- ------ --------
 I_PARAMETER1                   NUMBER                  IN
 I_PARAMETER2                   NUMBER                  IN
 O_PARAMETER1                   NUMBER                  OUT
 O_PARAMETER2                   NUMBER                  OUT

hr@ORCL>


SQL Server上的调用


DECLARE @l_i_parameter1 INTEGER
DECLARE @l_i_parameter2 INTEGER 
DECLARE @l_o_parameter1 INTEGER
DECLARE @l_o_parameter2 INTEGER

SET @l_i_parameter1 = 5
SET @l_i_parameter2 = 10
SET @l_o_parameter1 = 0
SET @l_o_parameter2 = 0

EXECUTE ( 'begin TEST_PKG.TestProcedure(?,?,?,?); end;', @l_i_parameter1, @l_i_parameter2, @l_o_parameter1 OUTPUT, @l_o_parameter2 OUTPUT) AT OraLink;

--OraLink为ORACLE 链接服务器
SELECT @l_o_parameter1, @l_o_parameter2 

/*
            
----------- -----------
6           11

*/

#8


回复:obuntu

我试了你的方法,可是还是不行呢?唉,郁闷了

#9


不知道提示什么错误。

#10


sql server 2000 不支持 execute(...) at server_link 语句。

对于 sql server 2000,需要将 oracle 的存储过程该为函数,
在 sql server 中使用 openquery(server_link,'select func from dual;') 执行。

#11


LZ

试下
10楼的可以不?

#12


引用 9 楼 obuntu 的回复:
不知道提示什么错误。


服务器: 消息 7357,级别 16,状态 2,行 1
未能处理对象 'declare 
finish varchar2(2);
errorinfo varchar2(50);
begin
P_BSHRP_inpbilling(195303,19722918,13046,1,01,finish,errorinfo);
end;
/'。OLE DB 提供程序 'MSDAORA' 指出该对象中没有任何列。
OLE DB 错误跟踪[Non-interface error:  OLE DB provider unable to process object, since the object has no columnsProviderName='MSDAORA', Query=declare 
finish varchar2(2);
errorinfo varchar2(50);
begin
P_BSHRP_inpbilling(195303,19722918,13046,1,01,finish,errorinfo);
end;
/']。

#13


引用 10 楼 xman_78tom 的回复:
sql server 2000 不支持 execute(...) at server_link 语句。

对于 sql server 2000,需要将 oracle 的存储过程该为函数,
在 sql server 中使用 openquery(server_link,'select func from dual;') 执行。


请教这个FUNC 如何写?

#14


哪位兄弟再给指导一下??

#15


引用 13 楼 pensheng 的回复:
请教这个FUNC 如何写?


这个需要具体问题具体分析。
如果要返回标量值,可以使用 select func from dual; 方法。但有以下要求:
由于此函数用于 sql 语句中,因此函数只能返回 sql 类型值,不能有 out 或 out in 参数,不能查询和修改 sql 语句引用的表,不能包含 dcl 和 ddl 语句。

如果要返回结果集,可以将存储过程改写为 pipelined 函数,使用 select ... from table(func); 方法调用。

#16


结贴前先感谢以下三位兄弟,谢谢你们的解答.
xman_78tom
obuntu
ws_hgo
------------------------------------------------------------------------------------
然后告诉大家我最后的解决办法,这办法其实是绕开了SQL SERVER 2000调用 ORCALE10g 的存储过程的方式,虽然解决了问题但还是很遗憾。不是我所希望的方式
------------------------------------------------------------------------------------
下面是解决的方法:
我在SQL里面用insert into 先写入到 orcale 的一张临时表中,然后在 orcale 中用一个作业去扫描这张表,读取参数往存储过程里面传,这样问题解决了。

本来是想在 orcale 的那张临时表上加个触发器,表里写数据就执行那个存储过程,无奈触发器好象有限制,里面不能INSERT INTO ,UPDATE,DELETE之类的操作。所以采用上述办法。

#1


。。。这样也行吗

#2


C.   使用用于   Oracle   的   Microsoft   OLE   DB   提供程序 
此示例创建一台名为   LONDON   Mktg   的链接服务器,该服务器使用用于   Oracle   的   Microsoft   OLE   DB   提供程序,并且假设此   Oracle   数据库的   SQL*Net   别名为   MyServer。 

USE   master 
GO 
--   To   use   named   parameters: 
EXEC   sp_addlinkedserver 
      @server   =   'LONDON   Mktg ', 
      @srvproduct   =   'Oracle ', 
      @provider   =   'MSDAORA ', 
      @datasrc   =   'MyServer ' 
GO 
--   OR   to   use   no   named   parameters: 
USE   master 
GO 
EXEC   sp_addlinkedserver   
      'LONDON   Mktg ',   
      'Oracle ',   
      'MSDAORA ', 
      'MyServer ' 
GO 


exec( 'delete   from   openquery(oracle_link, ' 'select   *     from   tt   where   t= ' '+@v+ ') ') 

#3


#4


回复:ws_hgo

你的这个方法是删除数据吧??我要的是一个存储过程,还有你个这是直接百度的吧?我早百度过N次了。不过还是谢谢

#5


http://blog.csdn.net/bugchen888/archive/2006/02/24/608152.aspx
这个网页前天我就百度到了,可是试了N次还是不行。好象有问题

#6


在ORCALE10G的 SQL*PLUS里执行下面语句能成功执行

declare 
finish float;
errorinfo varchar2(80);
begin
P_BSHRP_inpbilling(195303,19722918,13046,1,'01',finish,errorinfo); 
dbms_output.put_line(finish); 
dbms_output.put_line(errorinfo); 
end; 

#7


一个例子:

hr@ORCL> CREATE OR REPLACE PROCEDURE P_TEST(emp_id NUMBER) AS
  2      salary real;
  3    BEGIN
  4      SELECT salary INTO salary FROM employees WHERE employee_id = emp_id;
  5    END;
  6  /

过程已创建。

hr@ORCL> call p_test(100);

调用完成。

hr@ORCL> CREATE OR REPLACE PACKAGE test_pkg AS
  2  PROCEDURE TestProcedure
  3  (
  4      I_Parameter1 IN NUMBER,
  5      I_Parameter2 IN NUMBER,
  6      O_Parameter1 OUT NUMBER,
  7      O_Parameter2 OUT NUMBER
  8  );
  9  END;
 10  /

程序包已创建。

hr@ORCL> CREATE OR REPLACE PACKAGE BODY test_pkg AS
  2  PROCEDURE TestProcedure
  3  (
  4      I_Parameter1 IN NUMBER,
  5      I_Parameter2 IN NUMBER,
  6      O_Parameter1 OUT NUMBER,
  7      O_Parameter2 OUT NUMBER
  8  ) AS
  9  BEGIN
 10     O_Parameter1 := I_Parameter1 + 1;
 11     O_Parameter2 := I_Parameter2 + 1;
 12  END TestProcedure;
 13  END;
 14  /

程序包体已创建。

hr@ORCL> DESC TEST_PKG;
PROCEDURE TESTPROCEDURE
参数名称                       类型                    输入/输出默认值?
------------------------------ ----------------------- ------ --------
 I_PARAMETER1                   NUMBER                  IN
 I_PARAMETER2                   NUMBER                  IN
 O_PARAMETER1                   NUMBER                  OUT
 O_PARAMETER2                   NUMBER                  OUT

hr@ORCL>


SQL Server上的调用


DECLARE @l_i_parameter1 INTEGER
DECLARE @l_i_parameter2 INTEGER 
DECLARE @l_o_parameter1 INTEGER
DECLARE @l_o_parameter2 INTEGER

SET @l_i_parameter1 = 5
SET @l_i_parameter2 = 10
SET @l_o_parameter1 = 0
SET @l_o_parameter2 = 0

EXECUTE ( 'begin TEST_PKG.TestProcedure(?,?,?,?); end;', @l_i_parameter1, @l_i_parameter2, @l_o_parameter1 OUTPUT, @l_o_parameter2 OUTPUT) AT OraLink;

--OraLink为ORACLE 链接服务器
SELECT @l_o_parameter1, @l_o_parameter2 

/*
            
----------- -----------
6           11

*/

#8


回复:obuntu

我试了你的方法,可是还是不行呢?唉,郁闷了

#9


不知道提示什么错误。

#10


sql server 2000 不支持 execute(...) at server_link 语句。

对于 sql server 2000,需要将 oracle 的存储过程该为函数,
在 sql server 中使用 openquery(server_link,'select func from dual;') 执行。

#11


LZ

试下
10楼的可以不?

#12


引用 9 楼 obuntu 的回复:
不知道提示什么错误。


服务器: 消息 7357,级别 16,状态 2,行 1
未能处理对象 'declare 
finish varchar2(2);
errorinfo varchar2(50);
begin
P_BSHRP_inpbilling(195303,19722918,13046,1,01,finish,errorinfo);
end;
/'。OLE DB 提供程序 'MSDAORA' 指出该对象中没有任何列。
OLE DB 错误跟踪[Non-interface error:  OLE DB provider unable to process object, since the object has no columnsProviderName='MSDAORA', Query=declare 
finish varchar2(2);
errorinfo varchar2(50);
begin
P_BSHRP_inpbilling(195303,19722918,13046,1,01,finish,errorinfo);
end;
/']。

#13


引用 10 楼 xman_78tom 的回复:
sql server 2000 不支持 execute(...) at server_link 语句。

对于 sql server 2000,需要将 oracle 的存储过程该为函数,
在 sql server 中使用 openquery(server_link,'select func from dual;') 执行。


请教这个FUNC 如何写?

#14


哪位兄弟再给指导一下??

#15


引用 13 楼 pensheng 的回复:
请教这个FUNC 如何写?


这个需要具体问题具体分析。
如果要返回标量值,可以使用 select func from dual; 方法。但有以下要求:
由于此函数用于 sql 语句中,因此函数只能返回 sql 类型值,不能有 out 或 out in 参数,不能查询和修改 sql 语句引用的表,不能包含 dcl 和 ddl 语句。

如果要返回结果集,可以将存储过程改写为 pipelined 函数,使用 select ... from table(func); 方法调用。

#16


结贴前先感谢以下三位兄弟,谢谢你们的解答.
xman_78tom
obuntu
ws_hgo
------------------------------------------------------------------------------------
然后告诉大家我最后的解决办法,这办法其实是绕开了SQL SERVER 2000调用 ORCALE10g 的存储过程的方式,虽然解决了问题但还是很遗憾。不是我所希望的方式
------------------------------------------------------------------------------------
下面是解决的方法:
我在SQL里面用insert into 先写入到 orcale 的一张临时表中,然后在 orcale 中用一个作业去扫描这张表,读取参数往存储过程里面传,这样问题解决了。

本来是想在 orcale 的那张临时表上加个触发器,表里写数据就执行那个存储过程,无奈触发器好象有限制,里面不能INSERT INTO ,UPDATE,DELETE之类的操作。所以采用上述办法。