Oracle Procedure error (PLS-00428) - sql

This is the error message: PLS-00428: an INTO clause is expected in this SELECT statement. Meanwhile, this is the procedure for testing displaying the system date:
CREATE OR REPLACE
PROCEDURE "TEST_PROCEDURE"
AS
BEGIN
SELECT SYSDATE FROM DUAL;
END;
In the first place I don't need to use that INTO Oracle is insisting for me to do. Is there other way around beside using a cursor (I've seen it here https://stackoverflow.com/a/6029963/1983024)? I think it should not be like that, this does run normally just like in MS SQL without using INTO or cursor.

In the first place I don't need to use that INTO Oracle is insisting
for me to do.
The fact is, Oracle is correct: you do need to use an INTO to take the return value.
After all, if you want to display the result of the query you're going to need a variable to put it in first.

you can write
CREATE OR REPLACE
PROCEDURE "TEST_PROCEDURE"
AS
BEGIN
for r_row in ( SELECT SYSDATE s FROM DUAL)
dbms_output.put_line(r_row.s);
end loop;
END;
or you have to have a variable.
CREATE OR REPLACE
PROCEDURE "TEST_PROCEDURE"
AS
v_Date date;
BEGIN
SELECT SYSDATE into v_date FROM DUAL;
dbms_output.put_line(v_date );
END;
output format is dictated by your NLS_DATE_FORMAT setting, or you can be explicit like to_char(v_date, 'dd-mm-yyyy') etc.

Finally found a solution to the output I want (based on your responses) :D
CREATE OR REPLACE
PROCEDURE "TEST_PROCEDURE"
RET_DATE CHAR(10);
BEGIN
SELECT TO_CHAR(SYSDATE, 'MM/DD/YYYY') INTO RET_DATE FROM DUAL;
DBMS_OUTPUT.PUT_LINE(RET_DATE);
END;
This displays the SYSDATE with format of MM/DD/YYYY. Still, thanks for the replies and ideas (mostly #Jeffrey Kemp). Oracle just lengthens what MS SQL can normally do in one line :D

You can use like
CREATE OR replace PROCEDURE Test_procedure
IS
date CHAR(10);
BEGIN
SELECT To_char(SYSDATE, 'MM/DD/YYYY')
INTO date
FROM dual;
dbms_output.Put_line(date);
END;
it will return date into char format.
If you want to get date into date format just declare the date type variable then assign the sysdate value INTO that variable.Then use DBMS_OUTPUT.PUT_LINE(variable) to print the DATE.

If you wanted to do it in one line, you could also use:
CREATE OR replace PROCEDURE Test_procedure
IS
BEGIN
dbms_output.put_line(to_char(sysdate, 'MM/DD/YY'));
END;

Related

PLSQL-0043 - cannot be v_day into select / fetch

I am trying to write a PLSQL code to get current day name using PLSQL and assigning it to variable
Code
CREATE OR REPLACE PROCEDURE ABC_STORE
(
v_day varchar2
)
AS
BEGIN
select to_char(CURRENT_TIMESTAMP,'DAY') into v_day from dual;
DBMS_OUTPUT.PUT_LINE(v_day);
END;
Error :
You should add al least clause OUT for value v_day:
create or replace PROCEDURE ABC_STORE
(
v_day IN OUT varchar2
)
AS
BEGIN
select to_char(CURRENT_TIMESTAMP,'DAY') into v_day from dual;
DBMS_OUTPUT.PUT_LINE(v_day);
END;
Thank you
You don't need the query, because PL/SQL has an assignment operator :=.
You also don't need dbms_output if the requirement is just to bring back the day name.
Also, the 'DAY' format element includes blank padding by default (e.g. SUNDAY ), so 'fmDAY' provides the expected result SUNDAY. If it doesn't need to be all capitals, you can use 'fmDay'.
create or replace procedure day_name
( v_day out varchar2 )
as
begin
v_day := to_char(sysdate,'fmDay');
end day_name;
Just to add, if you are checking the day name as part of some business logic (for example, a batch step should not run at the weekend), you will also need to specify a date language to avoid the situation where you are checking for 'Sunday' and the procedure is called from a support desk in Paris and returns 'Dimanche'. You would do this using (for example - substitute any language you want)
to_char(sysdate,'fmDay','nls_date_language=English')
(Of course, if you were just checking for the weekend you would only need to get the English three letter abbreviation and check whether it's like 'S%', but this is not what you asked for. I mention it because I have seen production errors caused by poorly handled day name checks, and as a result I use it as an interview question, which it turns out very few candidates can answer.)

Having a hard time with procedure not formatting the query entry correctly

Create a dynamic procedure that will change the contents of any column for any row in the AA_EMPLOYEE table using the employee id. i.e.
BEGIN
dyn_aa_employee('emp_dob', '01-jan-18', 110);
END;
Will change the date of birth for employee ID 110
CREATE OR REPLACE PROCEDURE dyn_aa_employee
(p_col VARCHAR2,
p_dob IN aa_employee.emp_dob%TYPE,
p_id NUMBER)
IS
BEGIN
EXECUTE IMMEDIATE 'UPDATE aa_employee
SET '|| p_col ||' = :ph_dob
WHERE EMP_NUM = :ph_id'
USING p_dob, p_id;
BEGIN
dyn_aa_employee('emp_dob', '01-jan-18', 110);
END;
The top code has to work for the bottom code. The issue is it's changing the emp dob to 01-jan-0018, however I want it to change to exactly 01-jan-18.
My professor gave me a 0 for this assignment I'm just trying to figure out what I did wrong.
Assuming that aa_employee.emp_dob is of type date AND assuming that by '01-jan-18' you mean January 1st, 2018, either you do this:
BEGIN
dyn_aa_employee('emp_dob', date '2018-01-01', 110);
END;
or you could change your procedure to:
CREATE OR REPLACE PROCEDURE dyn_aa_employee (
p_col VARCHAR2,
p_dob IN aa_employee.emp_dob%TYPE,
p_id NUMBER)
IS
BEGIN
EXECUTE IMMEDIATE
'UPDATE aa_employee SET ' || p_col || ' = :ph_dob WHERE EMP_NUM = :ph_id'
USING TO_DATE (p_dob, 'DD-MON-YY'), p_id;
END;
It would be interesting to see the actual assignment, though. It's a rather confused scenario overall and I don't see how it teaches you much except to identify several things you probably shouldn't do.
Well first off you didn't specify the date format you were passing. Therefore accepting whatever format the professor had setup. This is a bad plan, to be safe always specify your date format and don't depend on the default. Defaults can and are changed too often. This is a good lesson why you should always specify the actual date format you're using. Try the following to see the difference:
with ds as
(select '01-jan-18' dt_stg from dual)
select to_date(dt_stg), to_date(dt_stg, 'dd-mon-rr') from ds;
Secondly, seems the assignment was to create a procedure that could update any column. This procedure can update only a column having the same type as "aa_employee.emp_dob%TYPE",presumable a date, but it cannot update any other column type.
Finally, if your trying to figure out what professor thinks you did wrong, then try something strange: ask your professor!

How to print record that caused ORA-01843 error?

I have a table with millions of records. I am trying to format one column data to DATE format
which is currently in VARCHAR2. But, I am getting ORA-01843 not a valid month error.
I am trying to get those records which are causing ORA-01843
CREATE OR REPLACE PROCEDURE pr_TEST_CUSTOM_ORA1843 AS
v_company MyTable.MyColumn%TYPE;
BEGIN
BEGIN
SELECT to_char(to_date(TRIM(MyColumn), 'YYMMDD'), 'MM/DD/YYYY')
INTO v_company FROM MyTable;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ORA-01843 caused by'||v_company);
END;
END pr_TEST_CUSTOM_ORA1843;
But, the value of v_company is not printed.
How to get the records which are causing ORA-01843 error?
I just commented on your previous question : How to format only those records for which ORA-01843 is not thrown? but you did not pay attention to it.
Create a function which checks if it is a valid date like this.
CREATE OR REPLACE FUNCTION validmmddyyyy (p_str IN VARCHAR2)
RETURN NUMBER
AS
V_date DATE;
BEGIN
V_Date := TO_DATE (p_str, 'MM/DD/YYYY');
RETURN 1;
EXCEPTION
WHEN OTHERS
THEN
RETURN 0;
END;
Then, to select the records which fail, you can run a query
select MyColumn FROM MyTable where validmmddyyyy(MyColumn) = 0
When you are lucky enough to use Oracle 12c R2, you could make use of DEFAULT..ON..CONVERSION ERROR clause of TO_DATE
SELECT *
FROM MyTable
WHERE TO_DATE (MyColumn default null on conversion error,'MM/DD/YYYY') IS NULL
An important advice as always, don't use a VARCHAR2 / CHAR type for DATEs in database.

SELECT command not being recognized for some reason.

For some reason, every time I try to run this, there is any error saying that the SQL statement at line 4, column 3 (SELECT) has been ignored. Also says, "YEAR": Invalid Identifier. Year is another column that exists on the same form. I am trying to make a column that displays the YEAR with a hyphen like for example this: "17-".
DECLARE
TERRA_NUMBER VARCHAR2(40);
BEGIN
SELECT CONCAT(YEAR , '-' )
INTO TERRA_NUMBER FROM DUAL;
RETURN TERRA_NUMBER;
END;
This is too long for a comment.
First, there is no YEAR variable in Oracle. Perhaps you intend TO_CHAR(sysdate, 'YYYY').
Second, an anonymous programming block does not return a value. So, RETURN is inappropriate.
If this is part of a function or stored procedure you should show the entire definition.
Maybe you can create FindYear function.
CREATE OR REPLACE FUNCTION FindYear RETURN VARCHAR2
IS
TERRA_NUMBER VARCHAR2(40);
BEGIN
SELECT CONCAT(TO_CHAR(sysdate, 'YYYY') , '-' )
INTO TERRA_NUMBER FROM DUAL;
RETURN(TERRA_NUMBER);
END;
/

Save value into a variable in oracle db

I have a query where i have to use the result of it multiple times. So instead of running the query multiple times i want to save the query value into a variable once and use it multiple times to accelerate the query speed.
for example:
Declare VAr = select M_DATE from TBT
If you want to do this in an interactive client, the answer depends on the client. For SQLPlus you could do this:
VARIABLE my_date VARCHAR2(10);
BEGIN
SELECT to_char(sysdate, 'YYYY-MM-DD' ) INTO :my_date FROM dual;
END;
/
PRINT my_date;
SELECT * FROM my_table WHERE date_column = TO_DATE( :my_date, 'YYYY-MM-DD' );
Note that SQLPlus does not support a DATE type for its variables, so you need to convert to a string when storing then back to a date when using the value. I recommend always using an explicit conversion and format string, simply to avoid unexpected results if the default format is not what you are expecting.
Within a PL/SQL block or procedure, it would be a little simpler:
DECLARE
l_mydate DATE;
BEGIN
SELECT sysdate INTO l_mydate FROM dual;
SELECT whatever INTO l_whatever FROM my_table
WHERE date_column = l_mydate;
<etc...>
END;
/
If you want to store the result of the query then you need to use a select ... into;
var v_storedate VARCHAR2(19);
exec select m_date into :v_storedate from tbt;
print v_storedate;
For an anonymous SQL block
begin
select m_date
into :v_storedate
from tbt;
end;
/