Why is "ADD_YEARS" an invalid identifier? - sql

I'm trying to use SQL's "ADD_YEARS" in an Oracle PLSQL Procedure.
However, (assuming it's actually to blame) it has an error on compilation: "invalid identifier".
I suspect that this is because the ADD_YEARS is something out of SQL, and not PLSQL. They don't seem to like each other. The only way I can think of doing this is to create a local variable and assign it the result I'd normally have gotten from ADD_YEARS. However, when I tried I couldn't figure out how to actually...assign some value to that. There's SELECT INTO but that makes 0 sense in this case.
-- If in good standing, extend membership 1 year.
-- If not but within grace (6 months), extend to 1 year from today.
-- Otherwise, explain renewal involves penalty. If no ID, print message.
CREATE OR REPLACE PROCEDURE renew(id1 IN member.id%type) IS
temp1 member.expr_date%type;
BEGIN
SELECT expr_date INTO temp1 FROM member WHERE id = id1;
IF temp1 > CURRENT_DATE THEN
UPDATE member
SET expr_date = ADD_YEARS(expr_date, 1)
WHERE id = id1;
ELSIF ADD_MONTHS(temp1, 6) > CURRENT_DATE THEN
UPDATE member
SET expr_date = ADD_YEARS(CURRENT_DATE, 1)
WHERE id = id1;
ELSE
dbms_output.put_line('Renewal will incur a penalty!');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('That ID does not exist as a member!');
END;
/
show errors
Here's the error I'm getting:
Errors for PROCEDURE RENEW:
LINE/COL ERROR
-------- -----------------------------------------------------------------
7/3 PL/SQL: SQL Statement ignored
8/19 PL/SQL: ORA-00904: "ADD_YEARS": invalid identifier
11/3 PL/SQL: SQL Statement ignored
12/19 PL/SQL: ORA-00904: "ADD_YEARS": invalid identifier
Thanks much for any help! I'm still very new to SQL and PL/SQL. Getting over some of its quirks has been difficult.

As mentioned in my comments, you cannot use ADD_YEARS since in Oracle nothing exist as ADD_YEARS. You can inturn use ADD_MONTHS or INTERVAL clause.
So you can modify your block update statement as :
SET expr_date = ADD_YEARS(expr_date, 1)
1) SET expr_date = ADD_MONTHS(expr_date, 12)
Or
2) SET expr_date = expr_date + interval '1' YEAR

Related

Create a parameterless procedure

I am trying to create a parameterless procedure that is used to take columns from a table and do some modifications to it and paste it into another table. But I am getting the following errors:
Procedure DEMO compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
4/2 PL/SQL: SQL Statement ignored
8/10 PLS-00403: expression 'NET.NETSALARY' cannot be used as an INTO-target of a SELECT/FETCH statement
8/24 PL/SQL: ORA-00904: : invalid identifier
Errors: check compiler log
My code used for this in sql is :
create or replace procedure "DEMO"
as
begin
case when comm is null then 0.9*grosssalary
when comm<500 then 0.85*grosssalary
else 0.8*grosssalary end
into net.netsalary from (select salary+comm as grossSalary,comm from
employee) ;
end ;
/
I am trying to insert the data into column netsalary of table net.
Please mention where did I go wrong?
Thanking you in advance.
Syntax is
CREATE OR REPLACE PROCEDURE demo
AS
BEGIN
INSERT INTO net (netsalary)
SELECT CASE
WHEN comm IS NULL THEN 0.9 * grosssalary
WHEN comm < 500 THEN 0.85 * grosssalary
ELSE 0.8 * grosssalary
END
FROM (SELECT salary + comm AS grossSalary, comm FROM employee);
END;
but it won't do much good. You're inserting as many rows as there are in the employee table, but ALL you insert is netsalary value - you don't even know who it belongs to.
Without knowing tables' description, it is difficult to guess what you really want to do.
insert? Probably employee number (or whatever that column name is) is missing
update? That's completely different command

Can't fix Error: PL/SQL Statement ignored

I've just started working with Triggers. While trying to compile the next code fragment errors are listed in the log, like so: "Error(2,3): PL/SQL: SQL Statement ignored" and "Error(2,7): PL/SQL: ORA-00922: missing or invalid option".
I don't understand the problem. Can anybody help?
CREATE OR REPLACE TRIGGER CONT_VIG
BEFORE INSERT ON CONTRACTS
FOR EACH ROW
WHEN (OLD.CLIENTID = NEW.CLIENTID AND OLD.ENDDATE > NEW.STARTDATE)
BEGIN
SET (OLD.enddate = :NEW.startdate-1);
END;
look this this-oracle and this-stackoverflow
try this:
CREATE TRIGGER hr.salary_check
BEFORE INSERT OR UPDATE OF salary, job_id ON hr.employees
FOR EACH ROW
WHEN (new.job_id <> 'AD_VP')
pl/sql_block
You can't change OLD value...
replace
SET (OLD.enddate = :NEW.startdate-1);
with for example :
:NEW.startdate := sysdate ;
(I removed SET because I don't see the usefulness)

Create a trigger

Create a trigger called NewEntry, that will not allow a result to be inserted into the student exam table if it is less than zero. In your query display a suitable message if the result is less than zero and supply code to test the trigger.
This is what I have done, but I keep getting
warning : trrigger created with compilation errors.
This is my code, please help!
CREATE OR REPLACE TRIGGER NewEntry
AFTER INSERT OR UPDATE ON Assignment2.Student_Exam
FOR EACH ROW
DECLARE
Results NUMBER;
BEGIN
IF(:NEW.Results < '0')
THEN
RAISE_APPLICATION_ERROR
(-20700,'Student's result cannot be less-than ZERO..Enter valid Results':);
ENDIF;
END;
/
END IF, not ENDIF. Also as Jeremy C mentions above you need to create the trigger as BEFORE INSERT OR UPDATE
you listen the other answers but one more thing ,
you must focus on :NEW.Results this is the thing.
There are two errors: Firstly it is 'END IF' not ENDIF, secondly you have apostrophe's in your message.
The correct code is:
CREATE OR REPLACE TRIGGER NewEntry
AFTER INSERT OR UPDATE ON Assignment2.Student_Exam
FOR EACH ROW
DECLARE
Results NUMBER;
BEGIN
IF(:NEW.Results < '0')
THEN
RAISE_APPLICATION_ERROR
(-20700, 'students result cannot be less-than ZERO..Enter valid Results:');
END IF;
END;
/
As others have said you could have de-bugged this yourself by typing show errors; This would have given you the answer e.g.
SQL> show errors;
Errors for TRIGGER NEWENTRY:
LINE/COL ERROR
-------------------------------------------------------------------------
7/18 PLS-00103: Encountered the symbol "S" when expecting one of the
following:
) , * & = - + < / > at in is mod remainder not rem =>
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
edit: In reply to Ersin - If it was New.Results then you would get a bind error e.g.
SQL> show errors;
Errors for TRIGGER NEWENTRY:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/4 PLS-00049: bad bind variable 'NEW.RESULTS'
SQL>
This will be a result of 'RESULTS' not being a column in Student_Exam, which I presume does exist given the rest of the statement.

Oracle Trigger create with compilation errors

I wrote the below trigger to prevent users from allocating a Class to a Session if the Class Date does not match the day of the week the Session is on.
CREATE OR REPLACE TRIGGER trig_alternative_classDate
AFTER INSERT OR UPDATE ON ALTERNATIVE
FOR EACH ROW
DECLARE
classdate CHAR;
sessionday VARCHAR;
BEGIN
SELECT to_char(to_date(class.class_date), 'Day') INTO classdate, sessions.day INTO sessionday
FROM SESSIONS, CLASS, DUAL, LOCATION, ALTERNATIVE
WHERE class.class_id = alternative.class_id
AND alternative.location_id = location.location_id
AND sessions.location_id = location.location_id;
IF sessions.day != to_char(to_date(class.class_date), 'Day')
THEN raise_application_error(-20999,'Invalid Class Date - Class Date does not match Session Day');
END IF;
END;
/
However I get an error message when I run the trigger
Warning: Trigger created with compilation errors.
SQL> show error trigger trig_alternative_classDate
Errors for TRIGGER TRIG_ALTERNATIVE_CLASSDATE:
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/2 PL/SQL: SQL Statement ignored
5/80 PL/SQL: ORA-00923: FROM keyword not found where expected
Could someone please help?
Remove second INTO - only one INTO is needed:
INTO classdate, sessions.day INTO sessionday

Using variables in PLSQL SELECT statement

I have a query that queries on ReportStartDate and ReportEndDate so I thought I would use variables in PLSQL. Not sure what I am missing here, but I get an error:
CLEAR;
DECLARE
varReportStartDate Date := to_date('05/01/2010', 'mm/dd/yyyy');
varReportEndDate Date := to_date('05/31/2010', 'mm/dd/yyyy');
BEGIN
SELECT
'Value TYPE',
1 AS CountType1,
2 AS CountType2,
3 AS CountType3
FROM DUAL;
SELECT COUNT (*)
FROM CDR.MSRS_E_INADVCH
WHERE 1=1
AND ReportStartDate = varReportStartDate
AND ReportEndDate = varReportEndDate
;
END;
/
The Error is:
Error starting at line 2 in command:
Error report:
ORA-06550: line 6, column 5:
PLS-00428: an INTO clause is expected in this SELECT statement
ORA-06550: line 8, column 5:
PLS-00428: an INTO clause is expected in this SELECT statement
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
This happens in Toad as well as in SQL Developer.
What is the proper way of using the variables in my WHERE clause?
You cannot use SQL statements directly in a PL/SQL block ( unless you use EXECUTE IMMEDIATE). The columns will need to be fetched into variables ( which is what PL/SQL is telling you with PLS-00428: an INTO clause is expected in this SELECT statement error). So you'll have to rewrite your statements as below.
SELECT
'Value TYPE',
1 AS CountType1,
2 AS CountType2,
3 AS CountType3
INTO
V_VALUE_TYPE,
V_CountType1,
V_CountType2,
V_CountType3
FROM DUAL;
SELECT COUNT(*)
INTO V_COUNT
FROM CDR.MSRS_E_INADVCH
WHERE 1=1
AND ReportStartDate = varReportStartDate
AND ReportEndDate = varReportEndDate
Be sure to add Exception Handlers, since PL/SQL expects only 1 row to be returned. If the statement returns no rows, you'll hit a NO_DATA_FOUND exception - and if the statement fetches too many rows, you'll hit a TOO_MANY_ROWS exception.
The question you have to answer is what do you want to do with the data that has been selected?
Sathya gave you one approach - declare variables in your PL/SQL block and select the columns INTO those variables. Note that this requires that the SELECT statement returns exactly one row - any more or less rows will throw an error. Another way is to declare collection types using the BULK COLLECT option: http://oracletoday.blogspot.com/2005/11/bulk-collect_15.html
Yet another option is to have the procedure return a cursor. This is useful in the case where the calling code expects to be able to fetch the data that the procedure has selected:
PROCEDURE GET_MY_REPORT( varReportStartDate in date, varReportEndDate in date, cur out sys_refcursor) is
begin
OPEN cur FOR SELECT *
FROM CDR.MSRS_E_INADVCH
WHERE 1=1
AND ReportStartDate = varReportStartDate
AND ReportEndDate = varReportEndDate;
END GET_MY_REPORT;