将 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 存储过程中将 varchar 转换为 int 时出错
如何将 SQL Server 存储过程迁移到 Mysql [关闭]
将用户定义表中的日期值传递给 SQL Server 2008 存储过程