An unexpected token "EXCEPTION" was found In PL/SQL(DB2) - plsql

I am Wrting a Stored Function As below in db2.
CREATE OR replace FUNCTION moc_enddate( IN v_date VARCHAR(6),
IN v_message VARCHAR(20)) returns DATE
BEGIN
DECLARE v_temp DATE;
DECLARE v_end_date DATE;
DECLARE v_temp_string VARCHAR(8) DEFAULT '01';
SET v_temp_string = v_temp_string
|| v_date;
SET v_temp = to_date(v_temp_string,'DDMMYYYY');
SET v_end_date = (v_temp + 19 days);
RETURN v_end_date;
EXCEPTION
WHEN no_data_found THEN
SET v_message = 'SqlDataException';
WHEN OTHERS THEN
SET v_message = 'OTHER';
END;
But I am getting the following Exception.
ERROR [42601] [IBM][DB2/AIX64] SQL0104N An unexpected token "EXCEPTION" was found following "RN V_END_MOC_DATE; ". Expected tokens may include.
"<psm_case>".

Maybe, you are using DB2 SQL PL instead of PL/SQL. There is a difference between these languages. If it's the case, the following condition should work:
create or replace procedure CreatePlants
begin
declare sqlstate char(5) default '00000';
declare ErrorMsg varchar(96);
declare exit handler for sqlexception
begin
set ErrorMsg = 'SQLSTATE=' concat sqlstate;
signal sqlstate '99001'
set message_text = ErrorMsg;
end;
create table plants
( ID dec(3), Location varchar(16),
primary key (ID));
label on table plants is 'Plant master';
insert into plants values
( 1, 'Lost Angeles'),
( 2, 'New Yolk'),
( 3, 'Last Vegas');
end
For more references see:
Error Handling in SQL PL, Part 1
Determine The State Of The Error

Related

Stored Procedure not reading from variable in IF-ELSE statement

I started writing this stored procedure and I faced some issues when I try to pass a variable in my conditional statement.
I can use the parameter BANKN which works fine, but when never I passed the declared variable AC_t somehow the PL/SQL ignores it.
Any idea please what I'm missing here?
create or replace PROCEDURE TTEST1 (
CR IN VARCHAR2,
BANKN IN VARCHAR2,
P_CURSOR OUT SYS_REFCURSOR
)
AS
G_AC CHAR(10);
AC_t Billing.Account %Type;
BEGIN
IF BANKN = 'WLNV' AND AC_t = 'Private'
THEN
IF CR IN (
'EUR',
'CZK',
'USD'
)
THEN
OPEN P_CURSOR
FOR
SELECT G_AC AS GL_ACC,
Billing.Account AS ACC_Type
INTO
G_AC,
AC_t
FROM Billing
INNER JOIN invoice ON Billing.ACC_NO = invoice.ACC_NO;
END IF ;
END IF ;
END;
My aim here is to expand this code by using AC_t value from Billing.ACCount and retrieve what ever data that can be 'Private' or 'Public'.
To do this, I need to use case or IF statement, however when I use
Billing.ACCount, I got an error "not allowed in this context", for this reason I use synonym AC_t but this don't read values from Billing table unless I use it in WHERE clause.
ACC_NO
Account
1
Private
2
Public
Extended code:
IF BANKN = 'WLNV' AND AC_t = 'Private'
THEN
...
...
ELSIF IF BANKN = 'WLNV' AND AC_t = 'Public'
THEN
....
...
You cannot use SELECT ... INTO with a cursor and you need to declare a value for the ac_t variable (but since it is a column in the table you may want a WHERE clause in the cursor). Like this:
CREATE PROCEDURE TTEST1 (
p_CR IN VARCHAR2,
p_BANKN IN VARCHAR2,
P_CURSOR OUT SYS_REFCURSOR
)
AS
BEGIN
IF p_BANKN = 'WLNV'
AND p_CR IN ( 'EUR', 'CZK', 'USD' )
THEN
OPEN P_CURSOR FOR
SELECT G_AC AS GL_ACC,
b.account AS ACC_Type
FROM Billing b
INNER JOIN invoice i
ON b.ACC_NO = i.ACC_NO
WHERE b.account = 'Private';
END IF;
END;
/
Which, if you have the sample data:
CREATE TABLE invoice (acc_no, g_AC) AS
SELECT 1, 2 FROM DUAL;
CREATE TABLE billing (acc_no, account) AS
SELECT 1, 'Private' FROM DUAL;
Then you can call the procedure and print the contents of the cursor using:
DECLARE
cur SYS_REFCURSOR;
v_g_ac INVOICE.G_AC%TYPE;
v_ac_t BILLING.ACCOUNT%TYPE;
BEGIN
ttest1('EUR', 'WLNV', cur);
LOOP
FETCH cur INTO v_g_ac, v_ac_t;
EXIT WHEN cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( v_g_ac || ', ' || v_ac_t );
END LOOP;
CLOSE cur;
END;
/
Which outputs:
2, Private
db<>fiddle here

MariaDB pl/sql to populate a table with dates from '1990-01-01' to '2000-12-31'

I attempt to create a procedure or function to populate a table name Time_Dim in MariaDB.
DELIMITER /
CREATE FUNCTION filltimeDim ()
BEGIN
DECLARE vQuarter VARCHAR(6);
DECLARE vMonth_Name VARCHAR(20);
DECLARE vdate_id date;
DECLARE vyear_id CHAR(4);
DECLARE vweekly_Name VARCHAR(20);
DECLARE vMonth_Num TINYINT(10);
DECLARE vweekday_Num TINYINT(10);
BEGIN
SET vdate_id = CONVERT('1998-01-01', DATE);
WHILE (CONVERT('vdate_id' USING utf8) <= '2002-12-31')
LOOP
SET vyear_id = YEAR(vdate_id);
SET vQuarter = QUARTER(vdate_id);
SET vMonth_Name = MONTHNAME(vdate_id);
SET vweekly_Name = DAYOFWEEK(vdate_id);
SET vMonth_Num = MONTH(vdate_id);
SET vweekday_Num = WEEKDAY(vdate_id);
INSERT INTO Time_Dim VALUES
(vdate_id, vyear_id, vquarter, vMonth_Name,vweekly_Name,vMonth_Num,vweekday_Num);
SET vdate_id = vdate_id + 1;
END LOOP;
END;
END; /
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOOP
SET vyear_id = YEAR(vdate_id);
SET vQuarter = QUA' at line 13
The syntax for while in MariaDB is:
[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
https://mariadb.com/kb/en/library/while/
You shouldn't use the 'LOOP' keywords
You can use Sequence Storage Engine:
-- SELECT
-- DATEDIFF('2002-12-31', '1990-01-01'); -- 4747
INSERT INTO `Time_Dim` (
`vdate_id`,
`vyear_id`,
`vquarter`,
`vMonth_Name`,
`vweekly_Name`,
`vMonth_Num`,
`vweekday_Num`
)
SELECT
`der`.`day`,
YEAR(`der`.`day`),
QUARTER(`der`.`day`),
MONTHNAME(`der`.`day`),
DAYOFWEEK(`der`.`day`),
MONTH(`der`.`day`),
WEEKDAY(`der`.`day`)
FROM (
SELECT
'1990-01-01' + INTERVAL (`seq`) DAY `day`
FROM
`seq_0_to_4747`
) `der`;
See dbfiddle.

Calling a stored procedure with CLOB output

I am trying to use the CLOB datatype as the output parameter in my stored procedure because its resultset exceeds the storage capacity of a var datatype.
How do I execute the procedure? Below are the commands I had run to execute.
I tried assigning the resultset to the the CLOB variable using the INTO query as shown in the query.
var cl CLOB;
EXECUTE procedure_name(:cl);
print cl;
How do i declare the binding variable because if you look at the first command, I am first initializing cl as var I am not able to initialize it as CLOB as it is giving out an error.
This is a sample of my procedure. The actual query in the procedure is 700 lines long.
CREATE OR REPLACE PROCEDURE procedure_name (cl OUT CLOB)
IS
BEGIN OPEN cl FOR
SELECT * FROM .....
statement 1
.
.
.
.
.
statement n
INTO cl
FROM
statement 1
.
.
.
statement n
EXCEPTION
WHEN
OTHERS THEN
DECLARE
err_num NUMBER := SQLCODE;
err_msg VARCHAR2(512) := SQLERRM;
error_id_pk NUMBER;
error_dt DATE;
BEGIN
SELECT (REGEXP_REPLACE(CURRENT_TIMESTAMP, '[^0-9]+', ''))INTO error_id_pk FROM DUAL;
SELECT SYSDATE INTO error_dt FROM DUAL;
INSERT INTO ODS_CONTROL.ERROR_DETAILS(ERROR_ID, ERROR_CODE, ERROR_DATE, PROCEDURE_NAME, ERROR_MSG)
VALUES ( error_id_pk,
err_num,
error_dt,
'PRC_FLEXI_CARD',
err_msg
);
END;
END;
Error message:
Error starting at line : 2 in command -
EXECUTE procedure_name( :clb )
Error report -
ORA-06550: line 1, column 7:
PLS-00905: object procedure_name is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
[TL;DR] VAR is a keyword for declaring a variable and is not a data type; your actual error is due to using invalid syntax when you tried to define your procedure and it has not compiled.
VAR is short for VARIABLE and defines a PL/SQL bind variable.
This declaration has the syntax:
VAR[IABLE] [variable [type] ]
where type represents one of the following:
NUMBER
CHAR
CHAR (n [CHAR | BYTE])
NCHAR
NCHAR (n)
VARCHAR2 (n [CHAR | BYTE])
NVARCHAR2 (n)
BLOB
BFILE
CLOB
NCLOB
REFCURSOR
BINARY_FLOAT
BINARY_DOUBLE
So with:
var cl CLOB;
you are declaring a variable using the VAR keyword and the variable is named cl and has the type CLOB.
Also, your CREATE PROCEDURE statement has a syntax error as you cannot have the single quotes around the procedure name. For example:
CREATE PROCEDURE procedure_name (clb OUT CLOB)
IS
BEGIN
clb := 'test';
END;
/
Then:
VAR cl CLOB;
EXECUTE procedure_name( :cl );
PRINT cl;
Outputs:
test
Updated:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE ERROR_DETAILS(
ERROR_ID NUMBER,
ERROR_CODE NUMBER,
ERROR_DATE DATE,
PROCEDURE_NAME VARCHAR2(30),
ERROR_MSG VARCHAR2(512)
)
/
CREATE PROCEDURE procedure_name (cl OUT CLOB)
IS
BEGIN
SELECT DUMMY
INTO cl
FROM dual
WHERE ROWNUM = 1;
EXCEPTION
WHEN
OTHERS THEN
DECLARE
err_num NUMBER := SQLCODE;
err_msg VARCHAR2(512) := SQLERRM;
BEGIN
INSERT INTO /* ODS_CONTROL. */ ERROR_DETAILS(
ERROR_ID,
ERROR_CODE,
ERROR_DATE,
PROCEDURE_NAME,
ERROR_MSG
) VALUES (
TO_NUMBER( TO_CHAR( CURRENT_TIMESTAMP, 'YYYYMMDDHH24MISSFF9' ) ),
err_num,
SYSDATE,
'PRC_FLEXI_CARD',
err_msg
);
END;
END;
/
Query 1:
SELECT * FROM USER_ERRORS
Results:
No rows selected

PL/SQL toolkit web application error when compiling procedure

I am trying to develop web application based on tutorial example. I have created procedure cilveki_list which has many parameters. When I compile this code I get two errors:
1)PL/SQL: SQL Statement ignored
2)PL/SQL: ORA-00933: SQL command not properly ended
First error refers to line 'c_kods in varchar2 default null'
and the second one to line ' if p_action = 'INSERT' then'.
Proedure behaviour depends on the parameter 'p_action', if it is set to 'INSERT', then insertion is perfomed, if it is set to 'UPDATE', then table update is performed.
But what is wrong with porcedue, why I get those errors, when I try to compile it?
create or replace package PACKAGE2 is
procedure cilveki_list(
c_vards in char default null,
c_uzvards in char default null,
c_dzimsanas_gads in number default null,
c_kods in varchar2 default null,
p_action in varchar2 default 'DISPLAY');
end PACKAGE2;
/
create or replace package body PACKAGE2 is
procedure cilveki_list(
c_vards in char default null,
c_uzvards in char default null,
c_dzimsanas_gads in number default null,
c_kods in varchar2 default null,
p_action in varchar2 default 'DISPLAY')
is
l_count number := 0;
begin
if p_action = 'INSERT' then
insert into CILVEKI
values ('',c_vards,c_uzvards,c_dzimsanas_gads,c_kods);
commit;
elsif p_action = 'UPDATE' then
UPDATE CILVEKI
set VARDS = c_vards,
UZVARDS = c_uzvards,
DZIMSANAS_GADS = c_dzimsanas_gads
WHERE PERS_KODS = c_kods;
commit;
end if;
htp.htmlOpen;
htp.bodyOpen;
htp.tableOpen;
htp.tableRowOpen;
htp.tableHeader('VARDS');
htp.tableHeader('UZVARDS');
htp.tableHeader('DZIMSANAS_GADS');
htp.tableHeader('PERS_KODS');
htp.tableRowClose;
for c1 in (select VARDS, UZVARDS, DZIMSANAS_GADS,PERS_KODS
from CILVEKI
order by UZVARDS) loop
htp.tableRowOpen;
htp.tableData(
htf.anchor(
curl => 'cilveki_modify?p_action=UPDATE&p_ticker=' || c1.VARDS,
ctext => c1.VARDS) );
htp.tableData( c1.UZVARDS );
htp.tableData( c1.DZIMSANAS_GADS );
htp.tableData( c1.PERS_KODS );
htp.tableRowClose;
l_count := l_count + 1;
end loop;
htp.tableClose;
htp.p( l_count || ' rows found');
htp.anchor( curl => 'cilveki_modify?p_action=INSERT',
ctext => 'Create New' );
htp.bodyClose;
htp.htmlClose;
end cilveki_list;
end PACKAGE2;
/
UPDATE CILVEKI
set VARDS = c_vards,
UZVARDS = c_uzvards,
DZIMSANAS_GADS = c_dzimsanas_gads,
WHERE PERS_KODS = c_kods
commit;
4th line above appears to be invalid. There shouldn't be a comma at the end of the line. Please remove the comma and re-compile the code.

Stored procedure for insert update and delete

I am very new to stored procedures. I have a table with an Id auto increment. I want to insert, update and delete rows in my table.
What is wrong with my stored procedure?
CREATE PROCEDURE [dbo].[hrm_Languages]
(
#Name varchar(120),
#CreatedBy bigint=0,
#UpdatedBy bigint=0,
#IsDeleted bit=0
#ID int OUTPUT
)
AS
BEGIN
SELECT #ID = ISNULL(MAX(ID), 0) + 1
FROM [dbo].[Languages]
IF #StatementType = 'Insert'
BEGIN
insert into [dbo].[Languages] (Name, CreatedOn, UpdatedOn, CreatedBy, UpdatedBy, IsDeleted)
values(#Name, DateTime(), DateTime, #CreatedBy, #UpdatedBy, #IsDeleted)
SELECT #Name
WHERE NOT EXISTS (SELECT ID, NAME
FROM TableName
WHERE NAME = #Name)
BEGIN
END
END
IF #StatementType = 'Select'
BEGIN
select * from [dbo].[Languages]
END
IF #StatementType = 'Update'
BEGIN
UPDATE [dbo].[Languages]
SET Name = #Name, UpdateOn = DateTime()
WHERE ID = #ID
END
else IF #StatementType = 'Delete'
BEGIN
DELETE FROM [dbo].[Languages] WHERE ID = #ID
END
end
Getting these errors:
Msg 102, Level 15, State 1, Procedure hrm_Languages, Line 7
Incorrect syntax near '#ID'.
Msg 137, Level 15, State 1, Procedure hrm_Languages, Line 12
Must declare the scalar variable "#ID".
Msg 137, Level 15, State 2, Procedure hrm_Languages, Line 15
Must declare the scalar variable "#StatementType".
Msg 195, Level 15, State 10, Procedure hrm_Languages, Line 17
'DateTime' is not a recognized built-in function name.
Msg 156, Level 15, State 1, Procedure hrm_Languages, Line 24
Incorrect syntax near the keyword 'END'.
Msg 137, Level 15, State 2, Procedure hrm_Languages, Line 26
Must declare the scalar variable "#StatementType".
Msg 137, Level 15, State 2, Procedure hrm_Languages, Line 31
Must declare the scalar variable "#StatementType".
Msg 195, Level 15, State 10, Procedure hrm_Languages, Line 34
'DateTime' is not a recognized built-in function name.
Msg 137, Level 15, State 2, Procedure hrm_Languages, Line 38
Must declare the scalar variable "#StatementType".
Msg 137, Level 15, State 2, Procedure hrm_Languages, Line 40
Must declare the scalar variable "#ID".
I also want to show message on my web page using label that Name inserted, Nme deleted, NAme already exist
OK, problems with your sproc (after reading it again), please see comments:
-- If you worked for me, I'd be having words about this name, it does not state
-- what this sproc does.
CREATE PROCEDURE [dbo].[hrm_Languages]
(
#Name varchar(120),
#CreatedBy bigint=0,
#UpdatedBy bigint=0,
#IsDeleted bit=0, -- You need a comma here. You hadn't posted your errors when I answered
-- this site isn't really for fixing your compile errors... read
-- the error text, it's quite helpful. Something wrong on line 7...
#ID int OUTPUT
)
AS
BEGIN
-- Problem 1. You are selecting this ID prior to inserting. This won't always be the
-- ID inserted, if your system is getting heavy use.
SELECT #ID = ISNULL(MAX(ID), 0) + 1
FROM [dbo].[Languages]
-- Problem 2. You don't pass in #StatementType - this won't even compile.
IF #StatementType = 'Insert'
BEGIN
insert into [dbo].[Languages] (Name,CreatedOn,UpdatedOn,CreatedBy,UpdatedBy,IsDeleted)
values( #Name, DateTime(), DateTime, #CreatedBy, #UpdatedBy,#IsDeleted)
-- To get the inserted ID, do the following
SELECT #ID = SCOPE_IDENTITY()
-- Not sure what the following is for.
SELECT #Name
WHERE NOT EXISTS (SELECT ID,NAME FROM TableName
WHERE NAME=#Name)
BEGIN
END
END
-- This is where your sproc should end and the following should be three other sprocs.
IF #StatementType = 'Select'
BEGIN
select * from [dbo].[Languages]
END
-- Problem 3. You don't seem to be passing in and ID, just for output, and you set the ID in the
-- first line. If your system is heavily used, this might just end up updating a newly inserted
-- row, but most likely will update nothing.
-- Same goes for the delete below. Create separate sprocs for doing these things.
IF #StatementType = 'Update'
BEGIN
UPDATE [dbo].[Languages] SET
Name = #Name, UpdateOn= DateTime()
WHERE ID = #ID
END
else IF #StatementType = 'Delete'
BEGIN
DELETE FROM [dbo].[Languages] WHERE ID = #ID
END
end
In addition to the Paddy's Answer you must use GetDate() Instead of DateTime() to get the current DateTime.
I have corrected stored procedure syntactically. I have written comments for changes I have made. Correct sql will create SP for you.
CREATE PROCEDURE [dbo].[hrm_Languages]
(
#Name varchar(120),
#CreatedBy bigint=0,
#UpdatedBy bigint=0,
#IsDeleted bit=0, -- Insert comma
#StatementType Varchar(20), -- Add variable #StatementType
#ID int OUTPUT
)
AS
BEGIN
IF #StatementType = 'Insert'
BEGIN
-- As #ID will reset again after insertion of record so following two line are not needed
SELECT #ID = ISNULL(MAX(ID), 0) + 1
FROM [dbo].[Languages]
SELECT #Name
WHERE NOT EXISTS (SELECT ID,NAME FROM TableName -- What is table name for
WHERE NAME=#Name)
insert into [dbo].[Languages] (Name,CreatedOn,UpdatedOn,CreatedBy,UpdatedBy,IsDeleted)
values( #Name, SYSDATETIME(), SYSDATETIME(), #CreatedBy, #UpdatedBy,#IsDeleted)
-- SysDateTime is used to get current datetime
SELECT #ID = SCOPE_IDENTITY()
End
ELSE IF #StatementType = 'Select'
Begin
select * from [dbo].[Languages]
END
ELSE IF #StatementType = 'Update'
BEGIN
UPDATE [dbo].[Languages] SET
Name = #Name, UpdatedOn = SYSDATETIME()
WHERE ID = #ID
END
ELSE IF #StatementType = 'Delete'
BEGIN
DELETE FROM [dbo].[Languages] WHERE ID = #ID
END
END

Resources