Why control statements is not working in Oracle Apex? - oracle

Is there any way around to make control statements work in apex?
SET SERVEROUTPUT ON;
DECLARE
v_num NUMBER := 12;
v_word VARCHAR := 'hello';
BEGIN
IF v_num < 10 THEN
DBMS.OUTPUT.PUT_LINE('IF condition executed.');
ELSIF v_word = 'hello' THEN
DBMS.OUTPUT.PUT_LINE('ELSIF condition executed.');
ELSE v_word = 'world' THEN
DBMS_OUTPUT.PUT_LINE('ELSE condition executed.')
END IF;
DBMS_OUTPUT.PUT_LINE('Outside the control statement.');
END;
This is the error I received every time I use control statements:

There are many little things wrong with your code. Start with the smallest possible piece, check it works and then add code - best way to start writing code in any language.
Issue 1: set serveroutput on is not needed in sql workshop. The server output is enabled by default and cannot be toggled. Try the following code:
BEGIN
dbms_output.put_line('hello');
END;
and observe it works.
Then run this code
set serveroutput on
and... notice that you get the same error you're reporting !
Issue 2: typos typos typos. Each commented line below causes an error
DECLARE
v_num NUMBER := 12;
--for VARCHAR, you need to declare the precision
--no error but datatype VARCHAR should NOT be used. Instead use VARCHAR2
--v_word VARCHAR := 'hello';
v_word VARCHAR2(100) := 'hello';
BEGIN
IF v_num < 10 THEN
-- typo: there is no "DBMS.OUTPUT"
--DBMS.OUTPUT.PUT_LINE('IF condition executed.');
DBMS_OUTPUT.PUT_LINE('IF condition executed.');
ELSIF v_word = 'hello' THEN
-- typo: there is no "DBMS.OUTPUT"
--DBMS.OUTPUT.PUT_LINE('ELSIF condition executed.');
DBMS_OUTPUT.PUT_LINE('ELSIF condition executed.');
--No condition needed after the ELSE keyword.
--ELSE v_word = 'world' THEN
ELSE
DBMS_OUTPUT.PUT_LINE('ELSE condition executed.');
END IF;
DBMS_OUTPUT.PUT_LINE('Outside the control statement.');
END;

Related

Encountered the symbol "2"

In this procedure I want to make a list of all procedures in my code and the user chooses a number to execute a certain procedure or function.
Here's my code
CREATE OR REPLACE PROCEDURE calling
IS
chosen VARCHAR2(1);
V_count NUMBER;
BEGIN
&chosen;
IF chosen='1' THEN
V_count:=visited.count_nb_city_visited(&idclient);
ELSIF chosen='2' THEN
V_count:=visited.max_vis;
visited.extract_best(V_count);
ELSIF chosen='3' THEN
ORDER_ORIGIN_CITY.ORDER_CITY;
ELSIF chosen='4' THEN
ORDER_ORIGIN_CITY.ORDER_CLIENT;
END IF;
END;
When running the code, this warning pops up "PLS-00103: Symbol "2" encountered (if I choose the number 2 and the same error is shown with any number I choose)
You can't (shouldn't) use substitution variables in a stored procedure as it will substitute the values in on compilation (and not as you are probably expecting on execution).
So if you substitute 2 for &chosen and 42 for &idclient then your code will be compiled as:
CREATE OR REPLACE PROCEDURE calling
IS
chosen VARCHAR2(1);
V_count NUMBER;
BEGIN
2;
IF chosen='1' THEN
V_count:=visited.count_nb_city_visited(42);
ELSIF chosen='2' THEN
V_count:=visited.max_vis;
visited.extract_best(V_count);
ELSIF chosen='3' THEN
ORDER_ORIGIN_CITY.ORDER_CITY;
ELSIF chosen='4' THEN
ORDER_ORIGIN_CITY.ORDER_CLIENT;
END IF;
END;
And will always execute with those fixed values.
You are getting the error because 2; is not a valid PL/SQL statement.
Instead, you should pass all the bind variables in the signature. Something like:
CREATE OR REPLACE PROCEDURE calling (
chosen IN NUMBER,
idclient IN NUMBER
)
IS
V_count NUMBER;
BEGIN
IF chosen = 1 THEN
V_count:=visited.count_nb_city_visited(idclient);
ELSIF chosen = 2 THEN
V_count:=visited.max_vis;
visited.extract_best(V_count);
ELSIF chosen = 3 THEN
ORDER_ORIGIN_CITY.ORDER_CITY;
ELSIF chosen = 4 THEN
ORDER_ORIGIN_CITY.ORDER_CLIENT;
END IF;
END;
/
If you want to call it from an anonymous PL/SQL block, then you can use substitution variables in that block:
BEGIN
calling(
chosen => &chosen,
idclient => &idclient
);
END;
/

Write a PL/SQL block to insert numbers into the MESSAGES table. Insert the numbers 1 through 10, excluding 6 and 8

I'm trying to figure out how to exclude these numbers(6 and 8) when the loop happens. Also, for this question, I CAN'T use FOR and WHILE loops. The question states to ONLY use a basic loop since the lessons after will teach me how to use it. Also, does anyone know if I'm allowed to insert multiple END LOOPs? It's also possible that this syntax may not be legal.
EDIT: I'm pretty sure I've tried doing IF v_results >10 THEN EXIT; but the same error message occurred.
DECLARE
v_results messages.results%TYPE := 0 ; --data type is NUMBER
BEGIN
LOOP
SELECT results INTO v_results
FROM messages;
v_results := v_results + 1; --to increment
IF v_results = ANY(6,8)
THEN
END LOOP; --i thought maybe if I added this, the loop can start over
ELSE
INSERT INTO MESSAGES(results)
VALUES (v_results);
EXIT WHEN v_results >10;
END IF;
END LOOP;
END;
The error that I am getting.
ORA-06550: line 15, column 9:
PLS-00103: Encountered the symbol "END" when expecting one of the following:
( begin case declare exit for goto if loop mod null pragma
raise return select update while with
<<
continue close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe purge
You could just avoid the 6 and 8 by adding 1 into it using the IF statement. There is no need for ELSE statement.
Also, you will need to use MAX function while fetching data from the MESSAGE table so that it can return the only max number. Without MAX function, you will get an error of -- multiple rows returned.
END LOOP must be associated with a single LOOP statement. so you can not write two END LOOP when there is a single LOOP statement.
DECLARE
V_RESULTS MESSAGES.RESULTS%TYPE := 0; --data type is NUMBER
BEGIN
LOOP
SELECT
MAX(RESULTS) -- used max to find ONLY ONE MAX RECORD
INTO V_RESULTS
FROM
MESSAGES;
V_RESULTS := NVL(V_RESULTS, 0) + 1; --to increment
IF V_RESULTS IN ( -- used in here
6,
8
) THEN
V_RESULTS := V_RESULTS + 1;
END IF;
INSERT INTO MESSAGES ( RESULTS ) VALUES ( V_RESULTS );
EXIT WHEN V_RESULTS >= 10;
END LOOP;
END;
db<>fiddle demo
Cheers!!
declare
i number:=1;
begin
loop
if i not in(6,8) then
insert into msg values(i);
end if;
i :=i+1;
exit when i>10;
end loop;
end;

How to get the output of an unnamed PL/SQL block in Oracle SQL Worksheet online? It's showing Unsupported Command for SET SERVEROUTPUT ON;

I'm trying PL/SQL on online Oracle SQL Worksheet - Live Oracle SQL.
I'm unable to display the output of the block, in spite of adding SET SERVEROUTPUT ON;
This is my code
SET SERVEROUTPUT ON;
declare
i number:=2;
j number:=0;
counter number:=0;
flag number;
begin
loop
if (i=2) then
counter:=counter+1;
dbms_output.put(i ||' ');
else
j:=2;
flag:=0;
loop
if(mod(i, j)=0) then
flag:=1;
end if;
exit when (i=j) or flag=1;
end loop;
if(flag=0) then
counter:=counter+1;
dbms_output.put(j ||' ');
end if;
end if;
i:=i+1;
exit when counter=10;
end loop;
end;
/
This is the console message
Unsupported Command
Statement processed.
Any idea how to get it working?
I actually changed dbms_output.put() to dbms_output.put_line() and it worked. Any idea how to make dbms_output.put() work?
I want the output in a single line.
DBMS_OUTPUT will only output to the console when a full line of output has been produced. If you only use DBMS_OUTPUT.PUT and don't call DBMS_OUTPUT.PUT_LINE or DBMS_OUTPUT.NEW_LINE then the output will sit in a buffer somewhere but will never be written to the console.
From the Oracle [DBMS_OUTPUT.PUT] documentation:
Usage Notes:
When you call PUT_LINE the item you specify is automatically followed by an end-of-line marker. If you make calls to PUT to build a line, then you must add your own end-of-line marker by calling NEW_LINE. GET_LINE and GET_LINES do not return lines that have not been terminated with a newline character.
You want to add DBMS_OUTPUT.NEW_LINE (or DBMS_OUTPUT.PUT_LINE( NULL )) at the end of your PL/SQL block.
A simplified version of your code (that only checks odd numbers) is:
DECLARE
i PLS_INTEGER :=1;
j PLS_INTEGER;
counter PLS_INTEGER :=1;
BEGIN
DBMS_OUTPUT.PUT('2 ');
LOOP
i:=i+2;
j:=3;
LOOP
EXIT WHEN mod(i, j)=0;
j:= j + 2;
END LOOP;
IF i = j THEN
-- prime found
DBMS_OUTPUT.PUT(i ||' ');
counter:=counter+1;
EXIT WHEN counter >= 10;
END IF;
END LOOP;
DBMS_OUTPUT.NEW_LINE;
END;
/
Which outputs:
2 3 5 7 11 13 17 19 23 29
Comment out that DBMS_OUTPUT.NEW_LINE; line and the procedure will not output anything as the buffer is never flushed to the console.
db<>fiddle here

PLS-00103: Encountered the symbol "1" when expecting one of the following: (

Wrote the following PLSQL script to produce a report and am getting the error messages
Error at line 5
ORA-06550: line 61, column 18:
PLS-00103: Encountered the symbol "1" when expecting one of the following:
(
I've been through the code many times and I cannot find the error. Any help would be greatly appreciated.
I'm currently working in Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
SET serveroutput ON size 1000000;
DECLARE
TYPE TITLE_RECORD_TYPE IS RECORD
(id number(19),
gaid varchar2(20),
artist_legal_name varchar2(510),
artist_display_title varchar2(510),
display_title varchar2(510),
category varchar2(255),
type varchar2(255),
sub_type varchar2(255));
TITLE_RECORD TITLE_RECORD_TYPE;
v_title varchar2(510);
v_artist varchar2(510);
v_total_rows_error number(20) := 0;
v_row_count number(10) := 0;
v_error_desc varchar2(200) := NULL;
v_error_code number(19);
CURSOR ARTIST_TITLE_CURSOR is
select track_artist,track_title
from asset_artist_title;
CURSOR QUERY_CURSOR is
select distinct g1.gaid,g2.legal_name,g1.artist_display_title,
g1.display_title,g1.category,g1.type,g1.sub_type
from gcdm_app_rpt.rpt_asset g1,
gcdm_app_rpt.rpt_artist g2
where g1.artist_id = g2.id
and g1.is_deleted <> 'Y'
and g1.is_core = 'Y'
and g2.is_core = 'Y'
and g1.title like v_title||'%'
and g1.artist_display_title like v_artist||'%';
BEGIN
OPEN ARTIST_TITLE_CURSOR;
LOOP
FETCH ARTIST_TITLE_CURSOR into v_artist,v_title;
EXIT WHEN ARTIST_TITLE_CURSOR%NOTFOUND or ARTIST_TITLE_CURSOR%NOTFOUND IS NULL;
SELECT count(*)
INTO v_row_count
FROM gcdm_app_rpt.rpt_asset g1,
gcdm_app_rpt.rpt_artist g2
WHERE g1.artist_id = g2.id
AND g1.is_core = 'Y'
AND g1.is_deleted <> 'Y'
AND g2.is_core = 'Y'
AND g1.title like v_title||'%'
AND g1.artist_display_title like v_artist||'%';
IF v_row_count < 1 THEN
v_error_desc := 'Matching Asset record for '||v_artist||' - '||v_title||' not found';
DBMS_OUTPUT.PUT_LINE('Error: '||v_error_desc||'.');
v_row_count := 0;
v_total_rows_error := v_total_rows_error + 1;
ELSE
OPEN QUERY_CURSOR
FOR i in 1..ARTIST_TITLE_CURSOR
LOOP
FETCH QUERY_CURSOR into TITLE_RECORD;
EXIT WHEN QUERY_CURSOR%NOTFOUND or QUERY_CURSOR%NOTFOUND IS NULL;
DBMS_OUTPUT.PUT_LINE(title_record.id,title_record.gaid,title_record.artist_legal_name,title_record.artist_display_name,
title_record.display_title,title_record.category,title_record.type,title_record.sub_type);
END LOOP;
CLOSE QUERY_CURSOR;
v_row_count := 0;
END IF;
END LOOP;
CLOSE ARTIST_TITLE_CURSOR;
DBMS_OUTPUT.PUT_LINE(chr(0));
IF v_total_rows_error > 0 THEN
DBMS_OUTPUT.PUT_LINE('Total Rows in error: '||v_total_rows_error);
END IF;
DBMS_OUTPUT.PUT_LINE(CHR(0));
EXCEPTION
WHEN OTHERS THEN
v_error_desc := SQLERRM;
v_error_code := SQLCODE;
DBMS_OUTPUT.PUT_LINE('Error: '||v_error_desc||' - '||v_error_code);
END;
It's line 67 in what you've posted, not 61, but still; this line is not right:
FOR i in 1..ARTIST_TITLE_CURSOR
You're trying to loop over a range of numbers - perhaps you wanted the number of records returned by the cursor, which you can't get - but your end 'number' is a cursor, so not legal in that context.
But it seems to be completely out of place anyway as you're looping over the QUERY_CURSOR records, so I wouldn't think the ARTIST_TITLE_CURSOR is relevant at this point. And you aren't attempting to use i. It looks like you can just remove that line.
More importantly, the previous line is missing a semi-colon:
OPEN QUERY_CURSOR;
Because it doesn't have one it's seeing the FOR and expecting a cursor query.
Following up on comments about why you have that FOR 1..v_row_count, it's still a bit redundant. You're limiting the number of fetches you do to match the count you got previously, from essentially the same query as you have in the cursor, which means you don't quite ever hit the EXIT WHEN QUERYCURSOR%NOTFOUND condition - that would come from the v_row_count+1 loop iteration. Normally you wouldn't know how many rows you expect to see before you loop over a cursor.
You don't really need to know here. The count query is repetitive - you're querying the same data you then have to hit again for the cursor, and you have to maintain the query logic in two places. It would be simpler to forget the count step, and instead keep a counter as you loop over the cursor; then handle the zero-rows condition after the loop. For example:
DECLARE
...
BEGIN
OPEN ARTIST_TITLE_CURSOR;
LOOP
FETCH ARTIST_TITLE_CURSOR into v_artist,v_title;
EXIT WHEN ARTIST_TITLE_CURSOR%NOTFOUND;
-- initialise counter for each ARTIST_TITLE
v_row_count := 0;
OPEN QUERY_CURSOR;
LOOP
FETCH QUERY_CURSOR into TITLE_RECORD;
EXIT WHEN QUERY_CURSOR%NOTFOUND;
-- increment 'found' counter
v_row_count := v_row_count + 1;
DBMS_OUTPUT.PUT_LINE(title_record.id
||','|| title_record.gaid
||','|| title_record.artist_legal_name
||','|| title_record
||','|| artist_display_name
||','|| title_record.display_title
||','|| title_record.category
||','|| title_record.type
||','|| title_record.sub_type);
END LOOP;
CLOSE QUERY_CURSOR;
-- now check if we found anything in the QUERY_CURSOR loop
IF v_row_count < 1 THEN
v_error_desc := 'Matching Asset record for '||v_artist||' - '||v_title||' not found';
DBMS_OUTPUT.PUT_LINE('Error: Matching Asset record for '
|| v_artist || ' - ' || v_title || ' not found.');
v_total_rows_error := v_total_rows_error + 1;
END IF;
END LOOP;
CLOSE ARTIST_TITLE_CURSOR;
--DBMS_OUTPUT.PUT_LINE(chr(0));
-- presumably this was meant to put out a blank line; use this instead
DBMS_OUTPUT.NEW_LINE;
IF v_total_rows_error > 0 THEN
DBMS_OUTPUT.PUT_LINE('Total Rows in error: '||v_total_rows_error);
END IF;
--DBMS_OUTPUT.PUT_LINE(CHR(0));
DBMS_OUTPUT.NEW_LINE;
END;
I've also taken out the exception handler because it isn't really adding anything; you'd see the code and message without it, even if you didn't have server output on; and catching WHEN OTHERS is a bad habit to get into.
You also don't need to declare your record type. You could use an implicit cursor anyway and avoid the type and variable completely, but even with the cursor definition you have, you could put this afterwards instead:
TITLE_RECORD QUERY_CURSOR%ROWTYPE;
There are various ways to open and loop over cursors, and you're using one of the more explicit ones - which isn't a bad thing for learning about them, but be aware of the options too.

How to declare and display a variable in Oracle

I would like to declare and display a variable in Oracle.
In T-SQL I would do something like this
DECLARE #A VARCHAR(10) --Declares #A
SELECT #A = '12' --Assigns #A
SELECT #A --Displays #A
How can I do this in Oracle.
If you're talking about PL/SQL, you should put it in an anonymous block.
DECLARE
v_text VARCHAR2(10); -- declare
BEGIN
v_text := 'Hello'; --assign
dbms_output.Put_line(v_text); --display
END;
If using sqlplus you can define a variable thus:
define <varname>=<varvalue>
And you can display the value by:
define <varname>
And then use it in a query as, for example:
select *
from tab1
where col1 = '&varname';
If you are using pl/sql then the following code should work :
set server output on -- to retrieve and display a buffer
DECLARE
v_text VARCHAR2(10); -- declare
BEGIN
v_text := 'Hello'; --assign
dbms_output.Put_line(v_text); --display
END;
/
-- this must be use to execute pl/sql script
Make sure that, server output is on otherwise output will not be display;
sql> set serveroutput on;
declare
n number(10):=1;
begin
while n<=10
loop
dbms_output.put_line(n);
n:=n+1;
end loop;
end;
/
Outout:
1
2
3
4
5
6
7
8
9
10
Did you recently switch from MySQL and are now longing for the logical equivalents of its more simple commands in Oracle? Because that is the case for me and I had the very same question. This code will give you a quick and dirty print which I think is what you're looking for:
Variable n number
begin
:n := 1;
end;
print n
The middle section is a PL/SQL bit that binds the variable. The output from print n is in column form, and will not just give the value of n, I'm afraid. When I ran it in Toad 11 it returned like this
n
---------
1
I hope that helps

Resources