I'm a student and I have this exercise: we have to write a function with 2 parameters, account number and withdrawal, and return the new balance of a bank account only if the account balance - withdrawal > Flow threshold
This is my code:
SET
serveroutput ON CREATE
OR REPLACE FONCTION Retrait (f_numcomp IN VARCHAR2, f_montant NUMBER(38, 3)) RETURN NUMBER(38, 3) AS v_compte compte % ROWTYPE;
v_solde compte.Solde % TYPE;
BEGIN
SELECT
* INTO v_compte
FROM
compte
WHERE
f_numcomp = compte.NUMEROCOMPTE;
IF (v_compte.Solde - f_montant) > v_compte.SeuilDebit
/*and compte.Etat != 'desactiver'*/
THEN v_solde := v_compte.Solde - f_montant;
UPDATE
compte
SET
Solde = Solde - f_montant
WHERE
f_numcomp = compte.NumeroCompte;
ELSE dbms_output.put_line('solde insufusant!');
END IF;
RETURN(v_solde);
END Retrait;
/
This is what I get:
Rapport d'erreur -
ORA-06550: Ligne 9, colonne 16 :
PLS-00103: Symbole "(" rencontré à la place d'un des symboles suivants :. ;
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I'm new here; I read some articles here but still didn't find the error
CodePudding user response:
FONCTION must be FUNCTION, but that was obviously just a typo in the request here, because the error you got is something else.
In the function declaration Oracle wants types without precision. I.e. NUMBER instead of NUMBER(38, 3).
CREATE OR REPLACE FUNCTION Retrait (f_numcomp IN VARCHAR2, f_montant NUMBER)
RETURN NUMBER
AS
v_compte compte%ROWTYPE;
v_solde compte.Solde%TYPE;
BEGIN
SELECT * INTO v_compte
FROM compte
WHERE f_numcomp = compte.NUMEROCOMPTE;
...
CodePudding user response:
You should be able to simplify the function to use a single UPDATE statement with a RETURNING clause (rather than SELECT and then UPDATE):
CREATE FUNCTION Retrait (
f_numcomp IN COMPTE.NUMEROCOMPTE%TYPE,
f_montant IN COMPTE.SOLDE%TYPE
) RETURN COMPTE.SOLDE%TYPE
AS
v_solde COMPTE.SOLDE%TYPE;
BEGIN
UPDATE compte
SET Solde = Solde - f_montant
WHERE f_numcomp = NumeroCompte
AND solde - f_montant > SeuilDebit
RETURNING solde INTO v_solde;
IF SQL%ROWCOUNT = 0 THEN
DBMS_OUTPUT.PUT_LINE('solde insufusant!');
END IF;
RETURN v_solde;
END Retrait;
/
However, it is not usual to have DML statements in a function; you would normally use a PROCEDURE and have an OUT parameter to return the value.
