Procedure with if/else - stored-procedures

I need to create a procedure that takes in a number greater than 0 and less than 1 to be used as a discount amount. I also need to create an exception if the user puts in a number outside my parameters.
I created the following procedure but it does not compile and I'm not sure where I've gone wrong. Any ideas?
CREATE OR REPLACE
PROCEDURE prod_disc
(p_disc IN DECIMAL)
IS
DECLARE
my_excep EXCEPTION;
BEGIN
UPDATE
xx_product
SET p_discount = (p_discount + p_disc)
WHERE p_qoh >= (p_min * 2);
IF p_disc > 0 OR p_disc < 1 THEN
RAISE my_excep;
END IF;
EXCEPTION
WHEN my_excep THEN
DBMS_OUTPUT.PUT_LINE('Error: Value must be greater than 0 and less than 1');
END;
/
SHOW ERRORS;
ORA-24344: success with compilation error
/

DECLARE is a surplus - remove it.
Also, instead of DBMS_OUTPUT.PUT_LINE, use RAISE_APPLICATION_ERROR because noone will ever see the result of the former (unless (s)he runs in in a tool that supports such an output. The latter will be seen everywhere.
Fixed, your code might look like this (I'm not checking its logic):
CREATE OR REPLACE PROCEDURE prod_disc (p_disc IN DECIMAL)
IS
my_excep EXCEPTION;
BEGIN
UPDATE xx_product
SET p_discount = (p_discount + p_disc)
WHERE p_qoh >= (p_min * 2);
IF p_disc > 0
OR p_disc < 1
THEN
RAISE my_excep;
END IF;
EXCEPTION
WHEN my_excep
THEN
raise_application_error (
-20000,
'Error: Value must be greater than 0 and less than 1');
END;
/

Please remove ; in EXCEPTION clause
OLD:
EXCEPTION;
WHEN my_excep THEN
DBMS_OUTPUT.PUT_LINE('Error: Value must be greater than 0 and less than 1');
NEW:
EXCEPTION
WHEN my_excep THEN
DBMS_OUTPUT.PUT_LINE('Error: Value must be greater than 0 and less than 1');

remove 'DECLARE' keyword
You can declare variables after the 'IS' keyword since its built as the declaration part of the procedure/function without putting the keyword 'DECLARE'

Related

In Ada, how do you change a constraint_error to a self-defined exception?

I am working with a linked list stack and I want it to get an Underflow error so I can see that it is working properly. It, however, keeps giving me a constraint error message where I want there to be the underflow message. Any tips on what to do would be helpful. I cannot put up the code at the current moment for my server is down but I will update this as soon as I can
Two ways : (okay, three...)
(1) The clean way : Ensure you don't violate the constraint in the underflow condition.
You may think it's slow because of the explicit check. However, regardless of whether that counts as premature optimisation, the check happens implicitly anyway to raise Constraint_Error. Whether this actually costs any time depends on your compiler and optimisation level. With a good compiler it probably won't.
Underflow_Error : Exception;
Declare
A,B,C : Natural;
D : Integer; -- a "bigger" type that can accommodate the worst case value
Begin
-- A := B - C; -- may raise constraint error
D := B - C;
if D < 0 then
raise Underflow_Error;
else
A := D;
end if;
End;
(2) Catch the constraint error and raise yours instead. This is unclean because any other Constraint Error in the same scope will (misleadingly) be converted to Underflow Error.
Underflow_Error : Exception;
Declare
A,B,C : Natural;
Begin
A := B - C; -- Let it raise constraint error
Exception:
when Constraint_Error => -- convert to my exception
raise Underflow_Error;
-- when others => raise; -- un-handled exceptions are passed upwards anyway
End;
(3) Variant of (2) Catch the constraint error, perform post mortem analysis and raise appropriately. The additional computation is only in the exceptional case, so has essentially no performance impact.
Underflow_Error : Exception;
Declare
A,B,C : Natural;
Begin
A := B - C; -- Let it raise constraint error
Exception:
when Constraint_Error => -- if appropriate, convert to my exception
if B - C < 0 then
raise Underflow_Error;
else
raise;
end if;
End;

How to call a stored function from a stored procedure and store the return value

When I do this in my stored procedure:
create procedure Proc1(
startdate IN TIMESTAMP,
ENDDATE IN TIMESTAMP
)
declare test_result number --line 55
test_result:=Stored_function1(startdate,enddate,11,13); --line 56
END;
SQL Developer throws 2 errors:
PLS-00103: Encountered the symbol "TEST_RESULT" when expecting one of the following: := . ( # % ; not null range default character The symbol "." was substituted for "TEST_RESULT" to continue.
PLS-00103: Encountered the symbol "END" when expecting one of the following: begin function pragma procedure subtype type current cursor delete exists prior
Stored_function1 is user defined, takes 4 parameters, and does not belong to any package. Where did I do wrong and how do I correct it? Thanks.
Without seeing more of it it's hard to tell, but it seems you have some syntax error(s) in your procedure. No DECLARE is needed, there should be a semi-colon at the end of line 55 and a BEGIN before line 56 at the least.
Here's a basic skeleton:
Create or replace procedure my_procedure as
test_result number;
BEGIN
test_result := Stored_function1(startdate, enddate, 11, 13);
END;

Invalid Pointer Operation on dynamic array free

I'm pretty newbie to Delphi, so be kind please.
I'm working on a software that allows users to customize its interface ( button's location, appearance, wtv) and some other stuff.
The problem is, i have a grid and i store a representation of its cells on a dynamic array of Boolean which represents which cells are occupied. But when i try to free that matrix Sometimes i get an invalid pointer operation. Sometimes there isnt any error, but other times i get that invalid pointer stuff.
Definition:
type
TMatrix = array of array of Boolean;
var
Matrix: TMatrix;
Initialization:
SetLength(Matrix, MyGrid.ColumnCollection.Count, MyGrid.RowCollection.Count);
Usage:
Mostly, these kind of operations are the only ones that i use with the matrix, and i'm sure that those variables col,row,colspan,rowspan never have values greater than the array boundary
//Checks if a set of cells are occupied
for i := column to (column + columnspan)-1 do
begin
for j := row to (row + rowspan)-1 do
begin
if Matrix[i, j] then
begin
valido := False;
end;
end;
end;
// if there isnt any cell occupied i can move a component to that location and i set the cells to true ( occupied)
if (valido) then
begin
for i := column to (column + colspan)-1 do
begin
for j := row to (row + rowspan)-1 do
begin
Matrix[i,j]:= True;
end;
end;
end
Free:
try
begin
SetLength(Matrix,0,0);
end;
except
on E : Exception do
begin
//todo
ShowMessage('Free: ' + E.Message);
end;
end;
I'm using FASTMM4 and i do get the memory leak warning, but i cant understand its contents..
What can possibly be causing this error?
Im using Delphi Xe6 Firemonkey
Any help will be appreciated.
Thanks
The most likely explanation for this is that you are writing outside the bounds of the array. There's not enough code for us to be sure that is the case, but the symptoms you report are invariably caused by out-of-bounds access.
Your next step is to get the compiler to write code that checks for our-of-bounds access. In your project options, in the compiler section, find the range checking option. Enable this option. Now the compiler will emit code that checks that your array indices are valid whenever you access the array. If your code fails the test, at runtime, an exception will be raised. This will make it blatantly obvious which part of your code is defective.

ADO Query treats goto labels as parameters

I'm facing an issue executing SQL script in a TADOQuery component. The script that's being executed has goto statements along with their corresponding labels, for example:
goto MyLabel
MyLabel:
--do something else
However, the TADOQuery is seeing these : characters and treating them as parameters (which they are not parameters), and gives me an error:
Parameter object is improperly defined. Inconsistent or incomplete information was provided
How can I instruct the TADOQuery to not try to consider these as parameters?
Set AdoQuery.ParamCheck to false.
Update
The OP said in a follow-up comment that the above was sufficient for his immediate problem but wouldn't have worked if the query had contained actual :parameters. Initially, I couldn't get it to work with those either.
However, looking at the code of TParameters.ParseSQL in ADODB (D7), the author seems to have anticipated colons being embedded in the SQL (I mean, before any :paramname(s) one might enter to act as place-holders for TParameters), by treating a doubled-up colon (::) as a special case. So I think the intent was that one should double up any colon one doesn't want treated as a TParameter. To see what I mean, see Memo1's contents:
(PartialDFM)
object Memo1: TMemo
Left = 32
Top = 112
Width = 297
Height = 113
Lines.Strings = (
'declare'
' #number int'
'select'
' #number = ?'
'if #number > 0 goto positive'
'if #number < 0 goto negative'
''
'select ''zero'''
''
'positive::'
' select ''positive'''
' goto'
' exitpoint'
'negative::'
' select ''negative'''
'exitpoint::')
end
object ADOQuery1: TADOQuery
Connection = ADOConnection1
Left = 64
Top = 24
end
Then, the following works for me (displaying "positive", "negative" or "zero" in a DBGrid according to the value assigned to AdoQuery1.Parameters[0].Value)
procedure TForm1.DoQuery;
begin
if AdoQuery1.Active
then AdoQuery1.Close;
// AdoQuery1.Prepared := True;
AdoQuery1.SQL.Text := Memo1.Lines.Text;
AdoQuery1.ParamCheck := False;
ADOQuery1.Parameters.Clear;
ADOQuery1.Parameters.CreateParameter('Param1', ftInteger, pdInput, 1, Null);
AdoQuery1.Parameters[0].Value := 666;
AdoQuery1.Prepared := True;
AdoQuery1.Open;
end;

Algol60 passing integer element of array as parameter - error bad type

I have following problem.
When I try to run the code with arun file.obj (I have compiled with algol.exe file)
BEGIN
INTEGER PROCEDURE fun(tab,index,lower,upper);
INTEGER tab,index,lower,upper;
BEGIN
INTEGER t;
text (1, "Start");
t := 0;
FOR index := lower STEP 1 UNTIL upper DO
t := t + tab;
fun := t;
END;
INTEGER ARRAY t[1:10];
INTEGER i,result,lower,upper;
lower := 1;
upper := 10;
FOR i := 1 STEP 1 UNTIL 10 DO
t[i] := i;
i := 1;
result := fun(t[i],i,lower,upper);
END FINISH;
I am still getting error:
ERROR 3
ADD PBASE PROC LOC
07D4 0886 1 13
083A 0842 0 115
The compiler I use is "The Rogalgol Algol60" product of RHA (Minisystems) Ltd.
Error 3 means "3 Procedure called where the actual and the formal parameter types do not match."
But I do not understand why. The reason of error is t[i] (If I change to i - it is ok).
Someone knows what I am doing wrongly?
I compile the code on the dosbox (linux)
Problem is that the index of the integer array that you're passing to your procedure isn't the same as the integer that he's expecting. I can't remember what an integer array is full of, but I guess it isn't integers... Have to admit I never use them, but can't remember why. Possibly because of limitations like this. I stick to Real arrays and EBCDIC ones.
You can almost certainly fix it by defining a new integer, j; inserting "j := t[i];" before your invocation of 'fun'; then invoking 'fun' with 'j' rather than t[i].
BTW you may want to make the array (and the 'for' loop) zero-relative. ALGOL is mostly zero-relative and I think it may save memory if you go with the flow.
Let me know if this helps....

Resources