将 SQL Server 存储过程转换为 Oracle 过程以从表中查询

Posted

技术标签:

【中文标题】将 SQL Server 存储过程转换为 Oracle 过程以从表中查询【英文标题】:Convert SQL Server stored procedure to Oracle procedure to query from tables 【发布时间】: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 ;

    我使用 % 作为默认查询参数来返回 SQL Server 中的所有值 在没有用户输入的情况下。我不确定我必须在 Oracle 中使用什么作为默认值才能全部返回。

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

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

【问题讨论】:

【参考方案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()) 
----
----

【讨论】:

以上是关于将 SQL Server 存储过程转换为 Oracle 过程以从表中查询的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 存储过程参数类型转换

在 SQL Server 存储过程中将 varchar 转换为 int 时出错

如何将 SQL Server 存储过程迁移到 Mysql [关闭]

将用户定义表中的日期值传递给 SQL Server 2008 存储过程

插入前Microsoft SQL Server转换中的存储过程

MS Access 查询转换为 Sql Server