【问题标题】:Convert SQL Server stored procedure to Oracle procedure to query from tables将 SQL Server 存储过程转换为 Oracle 过程以从表中查询
【发布时间】:2015-11-30 22:55:09
【问题描述】:

我正在尝试从 SQL Server 迁移到 Oracle 数据库。我必须将我的存储过程从 SQL Server 移动到 Oracle,它使用 INNER JOIN 从多个表中进行查询。我想在这里澄清几件事。

SQL Server 存储过程:

[dbo].[QueryAll] 
    @score1_min int = 0,
    @score1_max int = 999,  
    @type1 varchar (1) = '%',
AS
BEGIN
    SET NOCOUNT ON;

    SELECT * 
    FROM FUNIJ1 uni
    INNER JOIN CAPI99 api99 on api99.application_id = uni.application_id
    INNER JOIN CAPI41 api41 on api41.application_id = uni.application_id
    INNER JOIN CAPI10 api10 on api10.application_id = uni.application_id
    WHERE 
        api10.score1 BETWEEN @score1_min AND @score1_max 
        AND uni.type1 LIKE @type1
END

还有我的 Oracle 程序

create or replace PROCEDURE QUERYALL 
(
  SCORE1_MIN IN NUMBER DEFAULT 0 
, SCORE1_MAX IN NUMBER DEFAULT 999 
, TYPE IN VARCHAR2 
) 
AS 
BEGIN
    SELECT *
    FROM FUNIJ1 uni
    INNER JOIN CAPI99 on CAPI99.APPLICATION_ID = uni.APPLICATION_ID
    INNER JOIN CAPI41 on CAPI41.APPLICATION_ID = uni.APPLICATION_ID
    INNER JOIN CAPI10 on CAPI10.APPLICATION_ID = uni.APPLICATION_ID
    WHERE 
        CAPI10.score1 BETWEEN score1_min AND score1_max 
        AND uni.type LIKE type
END REPOQUERYALL ;
  1. 我使用 % 作为默认查询参数来返回 SQL Server 中的所有值 在没有用户输入的情况下。我不确定我必须在 Oracle 中使用什么作为默认值才能全部返回。

  2. 列表项 Oracle 在 SELECT * 之后使用新术语 INTO。我不确定在这种情况下是否需要使用 INTO 或光标。我不知道哪个适合这里以及如何使用它。

  3. 如果有人可以将此 SQL Server 传输到 Oracle 过程,我将不胜感激。我不确定我的 Oracle 是否 100% 正确。

【问题讨论】:

    标签: sql-server oracle stored-procedures oracle11g


    【解决方案1】:

    这是您需要了解的有关 Oracle 存储过程的内容 - 与 SQL Server 不同,您不能只在任何编程块中执行 SELECT ...,除非这是子选择或 select... into...

    如果目标是从过程中返回记录集,则在 Oracle 中,您必须添加一个 Sys_RefCursor 输出参数并使用您的 select 语句打开此引用游标。

    您并不遥远 - check this example 。记住,当您执行 Open <cursor_name> FOR ... 时,FOR 之后的内容可以是动态 SQL 字符串或只是编译的 SQL。

    【讨论】:

    • 谢谢 T.S.因此,当我添加“RefCursor”时,这些 Oracle 示例也提到了 IN 参数。这是强制性的吗?
    • 是的。如果要从Oracle 存储过程中返回数据,则需要声明Sys_refcursor 类型的output 参数才能返回此数据。另一种(类似的)方法是声明函数create or replace Function ... return sys_refcursor。但这确实是一回事。 Return 只是一种输出参数。所以,如果你使用存储过程,你可以返回多个引用游标。在 sql server 中,您可以简单地编写 select* from t1; select * from t2 - 您有 2 个结果集。在oracle中,对于每个select要返回的数据都需要sys_refcursor参数:Open p1..;Open p2
    • IN 参数仅在您需要它们将某些内容传递给 SP 时使用。引用光标必须是OUT
    • @TS,我像这样修改了我的代码,但我仍然犯了一些错误'创建或替换 PROCEDURE QUERYALL ( -------- , o_Cursor OUT SYS_REFCURSOR ) AS BEGIN OPEN o_Cursor从 QCFUNIJ1 uni 中选择; INNER-------- ------------- END REPOQUERYALL ;'
    • 我刚刚测试了它 - 它在 oracle create or replace procedure aa (pa in varchar2) as rc sys_refcursor; rec dual%rowtype; begin open rc for select * from dual where dummy like pa; fetch rc into rec; Dbms_Output.Put_Line(rec.dummy); end; / 测试中工作 --> begin EIDMADM.aa('%X'); end; / 所以,基本上,它在 LIKE 中可以正常工作,就像 SQL Server 一样。你现在面临语法问题,不是系统的
    【解决方案2】:

    这是对我使用 Sys_Cursor 的代码。感谢@TS 的帮助,引导我找到这个答案。

    create or replace PROCEDURE QUERYALL 
    (
    o_Cursor OUT SYS_REFCURSOR
    ) 
    AS 
    BEGIN
    O_Cursor := NULL;
    
    OPEN O_Cursor FOR
        SELECT * FROM FUNIJ1
        INNER JOIN CAPI99 on CAPI99.APPLICATION_ID = FUNIJ1 .APPLICATION_ID
        INNER JOIN CAPI41 on CAPI41.APPLICATION_ID = FUNIJ1 .APPLICATION_ID
        INNER JOIN CAPI10 on CAPI10.APPLICATION_ID = FUNIJ1 .APPLICATION_ID
        WHERE 
        ----
        ----
    END QUERYALL;
    

    当您在Java中使用此过程显示表格时,您需要将Sys_Cursor调用到Resultset中。

    String sp= "{CALL QUERYALL(?)}"; // Procedure calling with Sys_Cursor
    cst = con.prepareCall(sql);
    cst.registerOutParameter(1, OracleTypes.CURSOR);
    cst.executeUpdate();
    rs = (ResultSet) cst.getObject(1);              
    while(rs.next()) {
    ----
    ----
    }
    

    【讨论】:

      猜你喜欢
      • 2013-10-10
      • 1970-01-01
      • 2018-05-06
      • 2020-10-12
      • 1970-01-01
      • 2021-08-17
      • 1970-01-01
      • 2016-03-30
      • 1970-01-01
      相关资源
      最近更新 更多