1. Sybase to Oracle differences
Table below lists out the differences in the coding styles between Sybase and Oracle. There are subtle
differences in syntax and major differences around Update statements with joins and error handling.
Table 1 Comparison of Stored procedure to load currencies
if exists (select 1
from sysobjects CREATE OR REPLACE PROCEDURE SMPL_UPD_REF_CURRENCY
where name = 'smpl_upd_ref_currency' (o_ret_code OUT INTEGER)
and type = 'P') 2 1
begin
IS
/*
drop procedure smpl_upd_ref_currency
end 1
<HEADER>
go
<PROCEDURE>smpl_upd_ref_currency</PROCEDURE>
create procedure smpl_upd_ref_currency
<AUTHOR></AUTHOR>
as <DATE></DATE>
2
begin <DESCRIPTION>
-- Update FIN_CURRENCY with the reference data.
------------------------------------------------- </DESCRIPTION>
----------------
3
-- PROCEDURE: smpl_upd_ref_currency Modification History
-- AUTHOR: Date Revision By Modification
-- DATE:
3 -------- -------- ------- -------------------
-- <MODIFICATIONS>
-- DESCRIPTION: Update FIN_CURRENCY with the </MODIFICATIONS>
reference data.
-- </HEADER>
-- REVISION:
-- */
------------------------------------------------- k_proc CONSTANT VARCHAR2(30) := 'smpl_upd_ref_currency';
----------------
v_rc INTEGER;
-- v_err INTEGER; 4
------------------------------------------------- v_msg VARCHAR2(80);
---------------- v_section_id VARCHAR2(2);
-- Declare and initialize variables.
-- BEGIN
-------------------------------------------------
---------------- --
declare @rc int -----------------------------------------------------------
declare @err int ----
declare @err_type int 4 -- 1. Update the currency Data.
declare @log_type int --
declare @msg varchar(80) -----------------------------------------------------------
declare @proc varchar(30) ----
v_section_id := '01';
select @err_type = 1 v_msg := 'Updating currency name in fin_currency table';
select @log_type = 0
select @proc = 'smpl_upd_ref_currency' UPDATE fin_currency c
SET crrncy_name =
-- 5
(SELECT r.crrncy_name
-------------------------------------------------
FROM ref_currency r
----------------
WHERE c.crrncy_cd = r.crrncy_cd AND
-- 1. Update the currency data.
c.crrncy_name != r.crrncy_name)
--
WHERE EXISTS
-------------------------------------------------
(SELECT * FROM ref_currency r2 WHERE c.crrncy_cd =
----------------
r2.crrncy_cd AND
update fin_currency
c.crrncy_name != r2.crrncy_name);
set crrncy_name = r.crrncy_name
5
from fin_currency, ref_currency r v_rc := SQL%ROWCOUNT;
where fin_currency.crrncy_cd = r.crrncy_cd
and fin_currency.crrncy_name != r.crrncy_name smpl_util_pkg.smpl_log_info(k_proc, v_section_id,
v_msg, v_rc);
select @rc = @@rowcount, @err = @@error
select @msg = "Update currency name in --
fin_currency table" -----------------------------------------------------------
exec smpl_log @proc, '01', @log_type, @msg, ----
2. @rc, @err -- 2. Insert any new currency Data.
if (@err != 0) --
begin -----------------------------------------------------------
select @msg = "Error updating currency ----
name in fin_currency table" v_section_id := '02';
exec smpl_log @proc, '01e', @err_type, v_msg := 'Adding new currencies to the fin_currency
@msg, @rc, @err 6 table';
return -1
end INSERT INTO fin_Currency
(crrncy_cd,
-- crrncy_Name) 7
------------------------------------------------- (SELECT r.crrncy_cd,
---------------- r.crrncy_Name
-- 2. Insert any new currency data.
--
FROM ref_currency r
WHERE NOT EXISTS (SELECT s.crrncy_cd
-------------------------------------------------
FROM fin_Currency s
----------------
WHERE r.crrncy_cd = s.crrncy_cd));
insert fin_currency (
crrncy_cd, 7
crrncy_name
v_rc := SQL%ROWCOUNT;
)
smpl_util_pkg.smpl_log_info(k_proc, v_section_id,
select r.crrncy_cd, 8
v_msg, v_rc);
r.crrncy_name
from ref_currency r
where not exists (select s.crrncy_cd --
from fin_currency s -----------------------------------------------------------
where r.crrncy_cd = ----
s.crrncy_cd) -- 99. Procedure end.
-- 9
select @rc = @@rowcount, @err = @@error -----------------------------------------------------------
select @msg = "Add new currencies to ----
fin_currency table" v_section_id := '99';
exec smpl_log @proc, '01', @log_type, @msg, v_msg := 'Procedure completed successfully';
@rc, @err smpl_util_pkg.smpl_log_info(k_proc, v_section_id,
8 v_msg, NULL); -- Row count doesn't mean anything at this
point
if (@err != 0)
begin o_ret_code := 0;
select @msg = "Error adding new RETURN;
currencies to fin_currency table"
exec smpl_log @proc, '01e', @err_type, EXCEPTION
@msg, @rc, @err WHEN OTHERS THEN
6
return -1 -- SV, 2/27, A generic Exception handler; This is
end to simply exception handling in these procedures;
-- Any SQL exception in this procedure will be
-- captured here; If any specific exceptions are to be
------------------------------------------------- -- handled in any section, add a BEGIN and END
---------------- block there with local exception handler(s).
-- 99. Procedure end. 9 -- v_section_id is used to identify which SQL
-- (section) failed
-------------------------------------------------
---------------- o_ret_code := 1;
select @rc = 0, @err = @@error IF (v_section_id = '99') THEN
select @msg = "Procedure completed -- error was not due to update or insert; more
successfully" generic error - this is rare, but just in case
o_ret_code := 99;
exec smpl_log @proc, '99', @log_type, @msg, v_msg := 'Procedure completed with error';
@rc, @err ELSE
if (@err != 0) v_msg := 'Error ' || lower(v_msg);
begin END IF;
select @msg = "Procedure completed with smpl_util_pkg.smpl_log_error(k_proc, v_section_id
error" || 'e', v_msg, SQLCODE, SQLERRM);
exec smpl_log @proc, '99e', @err_type,
@msg, @rc, @err -- RAISE;
return -1 END smpl_upd_ref_currency;
end /
10
return 0
end
go 10
3. Notes:
1. Sybase allows DDL statements inside stored procedures. Oracle does not allow such inside
PL/SQL. If the procedures need to be dropped it will have to be done using dynamic SQL.
Luckily Oracle provides a REPLACE directive that lets the procedure to be overwritten. This
will change the procedure if it already exists and retain the permissions too.
2. IS instead of AS
3. Header comments will now be written in XML. This is not an Oracle requirement, but a nice to
have. We may be able to extract XML headers later to get formatted document.
4. Variables in Oracle are declared before BEGIN statement. Typical Oracle structure is
DECLARE BEGIN EXCEPTION END;
5. Oracle does not allow joins inside UPDATE or DELETE statements. A little convoluted sub-
query is required. Notice the same sub query is repeated in the WHERE clause with EXISTS to
simulate the join. If EXISTS was left out, Oracle will try to update every row in the table being
updated.
6. Error handling is different. Sybase allows status code of the procedure to be returned with a
RETURN <numeric value> statement. Oracle does not allow stored procedures to return any
values. In oracle, to mimic this, we could use the EXCEPTION handler. When the exception is
RAISEd inside the WHEN clause of the exception handler, the SQLCODE of the error is
returned back to calling procedure (or SQL*Plus). Another approach of using an OUT
parameter for status value is considered as well.
7. Insert syntax is very similar except an INTO is required in Oracle.
8. smpl_log procedure in Sybase is replaced with a packaged procedure smpl_util_pkg.smpl_log.
The reason for package is to isolate actual logging method used from calling procedures. And
also, with the package, we added some settings (variables) that will be available through the
session.
9. Statements that follow when the SQL statements executed successfully must be entered before
the EXCEPTION block inside the current PL/SQL block. If the program always ran without any
errors, the exception block will never be reached.
10. Typically a ‘/’ (forward slash) is required in SQL*Plus to run what’s in buffer. Statement
terminator character (‘;’) is required to end statements in Oracle.