Cant retrieve error from procedure in PL/SQL - exception

I'm starting to work with PL/SQL and learning how to write procedures and exceptions but I cant seem to grasp how to show an error. The procedure is a simple one, its only supposed to do simple math as you can see below:
create or replace
procedure get_simple_math
(n_num1 in number,
n_num2 in number,
n_answer out number,
n_err_code out number,
n_err_msg out varchar2)
as
begin
n_answer := (n_num1 / n_num2);
dbms_output.put_line('Answer is '||n_answer);
n_err_code := 0;
exception
when others
then
n_err_code := SQLCODE;
n_err_msg := 'Error in get_simple_math '||SQLERRM;
raise_application_error (-20002,n_err_msg);
end get_simple_math;
As you can see its nothing fancy, but I cant for the life of me get the block to run:
set serveroutput on
declare
n_answer number := 0;
n_err_code number;
n_err_msg varchar2;
begin
get_simple_math(10,5,n_answer);
end;
I'm assuming I need to declare the variables that are set to out, which is why they are there. I also tried adding them to the procedure execute like:
get_simple_math(10,5,n_answer,n_err_code,n_err_msg);
But that didn't seem to do the trick, so I am just looking for some help in solving this problem. Thanks in advance.

Run this and you'll get your answer:
declare
n_answer number := 0;
n_err_code number;
--> n_err_msg varchar2; -- Incorrect
n_err_msg varchar2(300); -- Correct
begin
--> get_simple_math(10,5,n_answer); -- Incorrect call to proc...
get_simple_math(10,5,n_answer, n_err_code, n_err_msg); -- add out parameters
end;
/
General suggestion for the procedure part: use substr - optional:
n_err_msg := 'Error in get_simple_math '||substr(SQLERRM, 1, 250);

Related

Can't show fractional part as .0 when value is a whole number

Here's the case:
uses
System.JSON;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
dd:Double;
aJsonObj:TJSONObject;
begin
dd := 100.0;
aJsonObj := TJSONObject.Create(TJSONPair.Create('DecimalValue',TJSONNumber.Create(dd)));
ShowMessage(aJsonObj.ToString);
end;
which shows
{"DecimalValue":100}
What I need is
{"DecimalValue":100.0}
I've tried to change JsonFormatSettings but I couldn't find a way to add the fractional part.
One of TJSONNumber constructors accepts a raw string value that will be used in resulting JSON string without further processing. It allows you to pre-format the value yourself:
procedure TForm1.Button1Click(Sender: TObject);
var
dd: Double;
aJsonObj: TJSONObject;
begin
dd := 100.0;
aJsonObj := TJSONObject.Create(
TJSONPair.Create('DecimalValue', TJSONNumber.Create(FormatFloat('0.0###', dd, GetJSONFormat))));
try
ShowMessage(aJsonObj.ToString);
finally
aJsonObj.Free;
end;
end;
Using the above snippet the value shows as:
{"DecimalValue":100.0}
You can even create 'whatever' as number:
aJsonObj := TJSONObject.Create(TJSONPair.Create('DecimalValue', TJSONNumber.Create('whatever')));
to get this (invalid) JSON:
{"DecimalValue":whatever}
Side note: you are responsible for releasing root JSON objects you create as they have no parent object to manage their lifetime. Use try..finally to Free the root object when you're done with it as you can see in the first code snippet. Too bad that the documentation itself tempts you not to cleanup.

MYSQL Stored Procedure to Iterate Json Array Data

I have a couple of columns that are json arrays that have datetime data like this:
["2017-04-18 11:05:00.000000"]
["2017-04-20 11:05:00.000000"]
["2017-04-22 11:05:00.000000"]
["2017-12-11 22:14:02.000000", "2017-12-11 22:14:08.000000", "2017-12-11 22:19:13.000000", "2017-12-11 22:20:44.000000", "2017-12-11 22:21:54.000000", "2017-12-11 22:23:09.000000"]
["2017-12-13 13:21:04.000000"]
["2017-12-14 13:10:44.000000", "2017-12-14 13:21:51.000000"]
["2017-12-15 13:27:21.000000", "2017-12-15 13:30:21.000000"]
["2017-12-16 15:15:22.000000"]
The goal is to parse out the datetime data and store it into a separate table from which I plan on doing some fun stuff. Currently, it only inserts the first record only, and it inserts it ~180000 times. My current code is:
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE i INTEGER DEFAULT 0;
DECLARE usages VARCHAR(4000);
-- declare cursor for employee email
DEClARE curUsages
CURSOR FOR
SELECT associated_usages from usagesTbl where associated_usages not like '[]';
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET finished = 1;
OPEN curUsages;
getUsages: LOOP
FETCH curUsages INTO usages;
IF finished = 1 THEN
LEAVE getUsages;
END IF;
WHILE i < JSON_LENGTH(usages) DO
INSERT INTO usagesTbl VALUES (JSON_EXTRACT(usages, CONCAT('$[',i,']')));
SET i = i + 1;
END WHILE;
SET i = 0;
END LOOP getUsages;
CLOSE curUsages;
END;
it seems that the while loop variable "i" is not increasing, and I am getting constantly stuck in the loop. The reason for me thinking this is that I pulled out the JSON_EXTRACT code and wrote this for testing:
set #i = 0;
select JSON_EXTRACT(associated_usages, CONCAT('$[',#i,']')) from usagesTbl where associated_usages not like '[]';
I can change the value of #i to whatever index I want and I get the right data. Im just stuck on why it doesn't work in the while loop during the stored procedure. Any help is greatly appreciated!
not sure if this could be the issue, but I see this:
DEClARE curUsages
Should be this:
DECLARE curUsages
Can it be the simple typo ? (the 1 for the L)
Fixed it! It somehow created an infinite loop that just kept on inserting data even when the stored proc said it was done running. I dropped and recreated the table, and changed the datatype of usages back from VARCHAR to json, and it worked like a charm.

How to get this function to work in Oracle 11G - PL/SQL

I'm new with PL/SQL I have a assignment where I need to make a function. The assignment is as follows:
> "Create a function 'afdeling_van:'
> - this function accepts a medewerkernummer(employee number) as argument
> - give the afdelingnummer(department number) from the medewerkernummer(employee number) back"
So I need to create a function with a parameter that returns a number. After that I probably need to add some code to make it return a medewerker(employee) number back.
I got pretty stuck with this one as I am really new to PL/SQL. What I do have at the moment is this:
declare
procedure afdeling_van(p_persoon in medewerkers.mnr%type)--table name with column name
is
begin
select med.mnr
from medewerkers med;
where mnr = p_persoon;
end afdeling_van;
begin
afdeling_van(10);
end;
It's not working for me. I have tried different solutions. But as I lack experience and I cannot find the solution or information that I need on the web. I am trying it to ask here
one other thing. I think it's similair to my problem. In the previous assignment I made a procedure instead of a function. The procedure is as follows:
declare
v_medewerker varchar2(50) := ontsla_med();
procedure ontsla_med(p_medewerkers in medewerkers.naam%type)
is
begin
delete from medewerkers
where naam = p_medewerkers;
end ontsla_med;
begin
ontsla_med('');
dbms_output.put_line('Medewerker: ' || v_medewerker || 'verwijdert uit medewerker, inschrijven en uitvoeringen bestand.' );
exception
when no_data_found then
dbms_output.put_line('Medewerker bestaat niet/ is al verwijderd.');
end;
/
this works except for the last dbms_output.put_line. If I remove the output line, then it will work and with the output line, it won't.
I hope my question is not too vague.
Thanks in advance.
You need to create a function instead of a procedure, and you've got a semi-colon in the wrong place. Try something like:
declare
nReturned_value MEDEWERKERS.AFDELINGNUMMER%TYPE;
FUNCTION afdeling_van(p_persoon in medewerkers.mnr%type) --table name with column name
RETURN MEDEWERKERS.AFDELINGNUMMER%TYPE
is
nAFDELINGNUMMER MEDEWERKERS.AFDELINGNUMMER%TYPE;
begin
select med.AFDELINGNUMMER
INTO nAFDELINGNUMMER
from medewerkers med
where mnr = p_persoon;
RETURN nAFDELINGNUMMER ;
end afdeling_van;
begin
nReturned_value := afdeling_van(10);
DBMS_OUTPUT.PUT_LINE('nReturned_value = ' || nReturned_value);
end;
Edit
In your second example, I don't believe that the line v_medewerker varchar2(50) := ontsla_med(); will compile. ontsla_med is a procedure rather than a function, and because procedures don't return anything they can't be used in an assignment statement.
However, v_medewerker is only used in the DBMS_OUTPUT line which you say causes a problem - thus, it may be that the compiler is eliminating the variable because it's not used if the DBMS_OUTPUT line is removed, thus eliminating the problem. Try changing the declaration to v_medwerker varchar2(50) := 'Hello'; and see if that helps.

DBAdvGrid Show Decimal numbers

I have mysql table and DBAdvGrid,
decimal numbers of mysql column are shown like 950, 450, 555.45
I would like to be always shown 2 digits after point. like 950.00
I tried event of dataset 'AfterOpen'
TFloatField(MyDs.FieldByName('Price')).DisplayFormat := '0.00';
but did not helps
any help would appreciate.
you can try (use the Dataset direct)
works with mysql and Zeos
(MyDs.FieldByName('Price') as TFloatField).DisplayFormat := '#####0.00';
to get what you want.
More information look here.
Delphi's Database Architecture
UPDATE
About the test
procedure TForm1.Button1Click(Sender: TObject);
begin
ZQuery1.Open;
end;
procedure TForm1.ZQuery1AfterOpen(DataSet: TDataSet);
begin
if CheckBox1.Checked then
(ZQuery1.FieldByName('gebuehr') as
TFloatField).DisplayFormat := '#####0.00';
end;
Field gebuehr Transl.(gebuehr == fee)
Without AfterOpen
With AfterOpen

function return varray error

I keep getting a error when i run this code, What wrong with the code?
create or replace function f_vars(line varchar2,delimit varchar2 default ',')
return line_type is type line_type is varray(1000) of varchar2(3000);
sline varchar2 (3000);
line_var line_type;
pos number;
begin
sline := line;
for i in 1 .. lenght(sline)
loop
pos := instr(sline,delimit,1,1);
if pos =0 then
line_var(i):=sline;
exit;
endif;
string:=substr(sline,1,pos-1);
line_var(i):=string;
sline := substr(sline,pos+1,length(sline));
end loop;
return line_var;
end;
LINE/COL ERROR
20/5 PLS-00103: Encountered the symbol "LOOP" when expecting one of
the following:
if
22/4 PLS-00103: Encountered the symbol "end-of-file" when expecting
one of the following:
end not pragma final instantiable order overriding static
member constructor map
Stack Overflow isn't really a de-bugging service.
However, I'm feeling generous.
You have spelt length incorrectly; correcting this should fix your first error. Your second is caused by endif;, no space, which means that the if statement has no terminator.
This will not correct all your errors. For instance, you're assigning something to the undefined (and unnecessary) variable string.
I do have more to say though...
I cannot over-emphasise the importance of code-style and whitespace. Your code is fairly unreadable. While this may not matter to you now it will matter to someone else coming to the code in 6 months time. It will probably matter to you in 6 months time when you're trying to work out what you wrote.
Secondly, I cannot over-emphasise the importance of comments. For exactly the same reasons as whitespace, comments are a very important part of understanding how something works.
Thirdly, always explicitly name your function when ending it. It makes things a lot clearer in packages so it's a good habit to have and in functions it'll help with matching up the end problem that caused your second error.
Lastly, if you want to return the user-defined type line_type you need to declare this _outside your function. Something like the following:
create or replace object t_line_type as object ( a varchar2(3000));
create or replace type line_type as varray(1000) of t_line_type;
Adding whitespace your function might look something like the following. This is my coding style and I'm definitely not suggesting that you should slavishly follow it but it helps to have some standardisation.
create or replace function f_vars ( PLine in varchar2
, PDelimiter in varchar2 default ','
) return line_type is
/* This function takes in a line and a delimiter, splits
it on the delimiter and returns it in a varray.
*/
-- local variables are l_
l_line varchar2 (3000) := PLine;
l_pos number;
-- user defined types are t_
-- This is a varray.
t_line line_type;
begin
for i in 1 .. length(l_line) loop
-- Get the position of the first delimiter.
l_pos := instr(l_line, PDelimiter, 1, 1);
-- Exit when we have run out of delimiters.
if l_pos = 0 then
t_line_var(i) := l_line;
exit;
end if;
-- Fill in the varray and take the part of a string
-- between our previous delimiter and the next.
t_line_var(i) := substr(l_line, 1, l_pos - 1);
l_line := substr(l_line, l_pos + 1, length(l_line));
end loop;
return t_line;
end f_vars;
/