【问题标题】:Run SQL Server Stored Procedure via Database Link from Oracle通过 Oracle 中的数据库链接运行 SQL Server 存储过程
【发布时间】:2011-07-28 21:31:45
【问题描述】:

参考How to execute an Oracle stored procedure via a database link,它在我的情况下不起作用。我不知道我错过了什么。

我在同一台计算机上有一个 SQL Server 实例和 Oracle 数据库。并在Oracle中创建数据库链接,名为ss

并且在 SQL Server 中有一个存储过程叫做dbo.test_proc

create proc dbo.test_proc
as
    print 'testing';

显然,它没有参数,也没有返回值。

我尝试通过数据库链接调用 Oracle 中的存储过程。但没有以下工作。

exec test_proc@ss;
exec "test_proc"@ss;
exec "dbo"."test_proc"@ss;
exec "dbo.test_proc"@ss;
exec "dbo..test_proc"@ss;

错误是这样的

PLS-00201: identifier 'test_proc@SS' must be declared
ORA-06550: line 1, column 7:

有什么可以帮助我的吗?我已经尝试了很长时间。谢谢!


上传图片用于查询sys.procedures以检查SQL Server中存储过程的存在并尝试通过数据库链接运行存储过程。 Image

【问题讨论】:

  • 尝试将您的 TSQL 存储过程更改为 CREATE PROCEDURE dbo.test_proc AS BEGIN SELECT 'testing' END
  • 虽然我更改了存储过程,但仍然出现同样的错误。
  • 你是如何定义你的链接的——你能发布你使用的 CREATE DATABASE LINK 命令吗?能否从 Oracle 数据库中对 SQL Server 数据库中的表发出简单的 select 语句并使其成功?
  • 是的。数据库链接工作正常。我可以做select * from INFORMATION_SCHEMA.TABLES@ss。我刚刚为结果上传了一张图片。谢谢!
  • 您是否也尝试过exec dbo.test_proc@ss;

标签: oracle sql-server-2008 dblink


【解决方案1】:

实际上可以通过 dg4odbc 调用存储过程或函数。我测试了 MS SQL Server 的数据库网关,无论如何它都无法原生支持 Sql Server 表/标量值函数。两者都需要依赖 DBMS_HS_PASSTHROUGH.EXECUTE_IMMEDIATE 来实现此功能。我们需要检索插入行的 id:

DECLARE
  RESULT NUMBER(8,2);
  val  INTEGER;
  c    INTEGER;
  nr   INTEGER;
BEGIN

  RESULT := DBMS_HS_PASSTHROUGH.EXECUTE_IMMEDIATE@mssqldb('select SCOPE_IDENTITY();');
  c := DBMS_HS_PASSTHROUGH.OPEN_CURSOR@mssqldb; 
  DBMS_HS_PASSTHROUGH.PARSE@mssqldb(c, 'select @@IDENTITY');
  LOOP
    nr := DBMS_HS_PASSTHROUGH.FETCH_ROW@mssqldb(c);
    EXIT WHEN nr = 0;
    DBMS_HS_PASSTHROUGH.GET_VALUE@mssqldb(c, 1, val);
  END LOOP;  
  DBMS_HS_PASSTHROUGH.CLOSE_CURSOR@mssqldb(c); 
  DBMS_OUTPUT.PUT_LINE('retrieved: ' || val);
END;

【讨论】:

    【解决方案2】:

    google了一阵子,终于发现我用的是dg4odbc,它支持在SQL Server中调用存储过程。

    http://forums.oracle.com/forums/thread.jspa?threadID=1131396&tstart=0

    但是,我的电脑是 Windows 7,所以我仍在寻找解决方案。谢谢!


    更新:jonearles 给了我一个棘手的想法,但它确实有效。请参阅下面的 cmets。

    【讨论】:

    • 如果无法直接调用存储过程,您可以通过触发器间接调用它。在 SQL Server 上创建一个表并添加一个触发器,该触发器在插入时调用该过程。然后创建一个向该表中插入一行的 Oracle 过程。
    • @jonearles:这真是个好主意!!!我想我可以用这个方法来动态调用存储过程!谢谢!!!
    【解决方案3】:

    这是您处理来自 SQLServer SP 的结果集的多列的方式。

    DECLARE
      l_cursor    BINARY_INTEGER;
      v_sql       VARCHAR2(32767);
      v_res_1     NUMBER;         -- change to suite your datatype in SQLServer
      v_res_2     VARCHAR2(100);  -- change to suite your datatype in SQLServer
    BEGIN
      v_sql := 'EXEC getRecords @parameter1=''somevalue'', @parameter2=''somevalue'';';
    
      l_cursor := DBMS_HS_PASSTHROUGH.open_cursor@sqlserver;
      DBMS_HS_PASSTHROUGH.parse@sqlserver(l_cursor,v_sql);
    
      DBMS_HS_PASSTHROUGH.BIND_VARIABLE@sqlserver (l_cursor,  1 ,v_res_1);
      DBMS_HS_PASSTHROUGH.BIND_VARIABLE@sqlserver (l_cursor,  2 ,v_res_2);
    
      WHILE DBMS_HS_PASSTHROUGH.fetch_row@sqlserver(l_cursor) > 0
      LOOP
        DBMS_HS_PASSTHROUGH.get_value@sqlserver(l_cursor, 1, v_res_1);
        DBMS_HS_PASSTHROUGH.get_value@sqlserver(l_cursor, 2, v_res_2);
    
        Dbms_Output.put_line('Result : ' || v_res_1 || ' - ' || v_res_2);
      END LOOP;
    
      DBMS_HS_PASSTHROUGH.close_cursor@sqlserver(l_cursor);
    END;
    

    我可以看到这是一岁的帖子,但其他人可能会偶然发现它。 :)

    对这种方法的性能仍有疑问。这里的专家对此的任何见解将不胜感激。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-19
      • 2011-09-01
      • 2011-11-07
      • 1970-01-01
      • 2019-02-05
      • 1970-01-01
      • 2018-07-25
      • 1970-01-01
      相关资源
      最近更新 更多