PLSQL Quoted String Not Properly Terminated [closed] - sql

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I am unable to find the error with a quoted string not properly ended. I've looked everywhere and my syntax seems to be correct. The issue only came about when I introduced the if statement. Any ideas would be appreciated. Thanks. Let me know if you need more information.
declare
bk_id book.book_code%type;
bk_authorName author.author_first%type;
bk_authorLastName author.author_last%type;
bk_title book.title%type;
bk_pubcode book.publisher_code%type;
bk_category book.type%type;
bk_price book.price%type;
bk_paper book.paperback%type;
TempData := 10;
cursor book_cursor is select author.author_first, author.author_last, book.title, book.type, book.price from book, author, wrote where book.book_code=wrote.book_code and author.author_num=wrote.author_num;
begin
open book_cursor;
dbms_output.put_line('First Name Last Name Title Type Price');
dbms_output.put_line('________________________________________________________________________');
dbms_output.put_line('Date: '||Systimestamp);
loop
fetch book_cursor into bk_authorName, bk_authorLastName, bk_title, bk_category, bk_price;
if(bk_price<TempData) then
dbms_output.put_line(bk_authorName || ' ' || bk_authorLastName || ' ' || bk_title || ' ' || bk_category || ' ' || bk_price || 'Special Deal');
else
dbms_output.put_line(bk_authorName || ' ' || bk_authorLastName || ' ' || bk_title || ' " || bk_category || ' ' || bk_price);
end if;
exit when book_cursor%notfound;
end loop;
close book_cursor;
end;

Actually the problem with this syntax is you used double quotes instead of single quotes.
This is the corrected code. Try this,it should work.
declare
bk_id book.book_code%type;
bk_authorName author.author_first%type;
bk_authorLastName author.author_last%type;
bk_title book.title%type;
bk_pubcode book.publisher_code%type;
bk_category book.type%type;
bk_price book.price%type;
bk_paper book.paperback%type;
TempData := 10;
cursor book_cursor is select author.author_first, author.author_last, book.title, book.type, book.price from book, author, wrote where book.book_code=wrote.book_code and author.author_num=wrote.author_num;
begin
open book_cursor;
dbms_output.put_line('First Name Last Name Title Type Price');
dbms_output.put_line('________________________________________________________________________');
dbms_output.put_line('Date: '||Systimestamp);
loop
fetch book_cursor into bk_authorName, bk_authorLastName, bk_title, bk_category, bk_price;
if(bk_price<TempData) then
dbms_output.put_line(bk_authorName || ' ' || bk_authorLastName || ' ' || bk_title || ' ' || bk_category || ' ' || bk_price || 'Special Deal');
else
dbms_output.put_line(bk_authorName || ' ' || bk_authorLastName || ' ' || bk_title || ' ' || bk_category || ' ' || bk_price);
end if;
exit when book_cursor%notfound;
end loop;
close book_cursor;
end;

Related

Convert dbms_output to html and selectively suppress other output

I am using the code below which outputs as intended:
DECLARE
v_ins_param VARCHAR2(10);
CURSOR c_ins_param IS
SELECT status
FROM v$instance;
BEGIN
OPEN c_ins_param;
LOOP
FETCH c_ins_param INTO v_ins_param;
EXIT WHEN c_ins_param%NOTFOUND;
--
--
--
IF v_ins_param = 'OPEN' THEN
DBMS_OUTPUT.PUT_LINE('
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || '
Great! Your database is up.
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || ' ');
ELSIF v_ins_param = 'MOUNTED' THEN
DBMS_OUTPUT.PUT_LINE('
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || '
Database is only mounted.
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || '
');
ELSE
DBMS_OUTPUT.PUT_LINE('
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || '
Database is neither mounted or open.
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || '
');
END IF;
END LOOP;
CLOSE c_ins_param;
END;
/
This is the "kind" of output it'll give you:
###
Great! Your database is up.
###
Ultimately this will be a series of anonymous block "typed" scripts like this one which I want to output to a single file.
I am now trying to get the output to just give the text information only, in a html output. I saw this on another page and adapted it for my code to see how it would / could work:
spool c:mag.html
DECLARE
CURSOR c1 IS
SELECT * FROM dept;
BEGIN
DBMS_OUTPUT.PUT_LINE('< pre >');
DBMS_OUTPUT.PUT_LINE('< h1 >Report on Databases</h1>');
FOR mag IN c1
LOOP
EXIT WHEN c1%notfound;
DBMS_OUTPUT.PUT_LINE('< b >Department Name[/b] =' || mag.dname);
END LOOP;
END;
/
However the way of doing this, using:
mag.dname
is not applicable in my 'non for loop' example.
I feel like there must be a more appropriate way of achieving the output. I have tried:
set markup html on
And it does not just returned impact the output but ALL of the code.
Has anyone tried this before and know perhaps how I might get the html output for the returned data only?
Here's an example - I store the following in a script called (say) scr.sql
set termout off
set feedback off
set serverout on
begin
for i in (
select
case
when status = 'OPEN' then '<p>Database is open</p>'
when status = 'MOUNTED' then '<p>Database is mounted</p>'
else '<p>Database is not happy</p>'
end status_output
from v$instance
)
loop
dbms_output.put_line(i.status_output);
end loop;
end;
.
spool /tmp/status.html
/
spool off
and then run this from SQLPlus as
SQL> #scr.sql
and the only thing my resultant status.html is
<p>Database is open</p>

continuing loops a thing in oracle

I am carrying out another exercise to learn various things about Oracle SQL's syntax today's lesson I've chosen are loops. Please see below code where I am trying to have two fields (temp variables) having values being decreased until it's less than zero depending on which of the variables hit's zero depends on what text I would like to output into the script output. Hopefully it makes sense. If I have made any faux pas's please do shout at me.
DECLARE
"Character" VARCHAR2(255);
"Enemy" VARCHAR2(255);
"Character_Health" NUMBER;
"Enemy_Health" NUMBER;
"Character_Attack" NUMBER;
"Enemy_Attack" NUMBER;
BEGIN -- Generates Base Stats
SELECT 'Hero' INTO "Character" FROM dual;
SELECT 'Villain' INTO "Enemy" FROM dual;
SELECT 100 INTO "Character_Health" FROM dual;
SELECT 25 INTO "Enemy_Health" FROM dual;
SELECT 10 INTO "Character_Attack" FROM dual;
SELECT 5 INTO "Enemy_Attack" FROM dual;
dbms_output.put_line ("Character" || ' (' || "Character_Health" || ') VS ' ||' '|| "Enemy" || ' (' || "Enemy_Health" || ')') ;
dbms_output.put_line ('');
dbms_output.put_line ('FIGHT!');
BEGIN -- Round 1
LOOP
dbms_output.put_line ('');
SELECT "Enemy_Health" - "Character_Attack" INTO "Enemy_Health" FROM dual; -- Hero hits Villain
dbms_output.put_line ("Character" || ' Hits ' || "Enemy" || ' for ' || "Character_Attack" ||' Damage' );
dbms_output.put_line ("Enemy" || ' Has ' || "Enemy_Health" || ' Health Remaining ');
CASE WHEN "Enemy_Health" < 0 THEN dbms_output.put_line ("Enemy" || 'Has Fainted' || "Character" || 'Wins!');
ELSE CONTINUE;
EXIT WHEN "Enemy_Health" < 0;
SELECT "Character_Health" - "Enemy_Attack" INTO "Character_Health" FROM dual; -- Villain hits Hero
dbms_output.put_line ('');
dbms_output.put_line ("Enemy" || ' Hits ' || "Character" || ' for ' || "Enemy_Attack" ||' Damage' );
dbms_output.put_line ("Character" || ' Has ' || "Character_Health" || ' Health Remaining ');
CASE WHEN "Character_Health" < 0 THEN dbms_output.put_line ("Character" || 'Has Fainted' || "Enemy" || 'Wins!');
ELSE CONTINUE;
EXIT WHEN "Character_Health" < 0;
END LOOP;
END;
END;
I found some errors
1. Syntax for case is:
CASE [ expression ]
WHEN condition_1 THEN result_1
WHEN condition_2 THEN result_2
...
WHEN condition_n THEN result_n
[ELSE result]
END CASE
Learn more:
- simple case statement
- searched case statement
CONTINUE stops processing loop and starts it from the begining, so your logic is corrupt - only Hero is attacking.
You need space after "Fainted"
It's better to use IF in this case:
IF "Character_Health" < 0
THEN
dbms_output.put_line ("Character" || 'Has Fainted. ' || "Enemy" || 'Wins!');
EXIT;
END IF;
It's not mistake, but you don't need select into from dual if you want to change value of variable.
Last but not least- i don't like how you use variables. "Character_Health" is similar to 'Character_Health' or '''Character_Health'''. Better use names like characterHealth or character_health.
My version would be something like that:
DECLARE
v_Character VARCHAR2(255) := 'Hero' ;
v_Enemy VARCHAR2(255) := 'Villain';
v_Character_Health NUMBER := 100;
v_Enemy_Health NUMBER := 25;
v_Character_Attack NUMBER := 10;
v_Enemy_Attack NUMBER := 5;
v_nl VARCHAR2(1) := chr(10);
BEGIN
dbms_output.put_line (v_Character || ' (' || v_Character_Health || ') VS ' ||' '|| v_Enemy || ' (' || v_Enemy_Health || ')' || v_nl) ;
dbms_output.put_line ('FIGHT!' || v_nl);
LOOP
v_Enemy_Health := v_Enemy_Health - v_Character_Attack;
dbms_output.put_line (v_Character || ' Hits ' || v_Enemy || ' for ' || v_Character_Attack ||' Damage' );
dbms_output.put_line (v_Enemy || ' Has ' || v_Enemy_Health || ' Health Remaining' || v_nl);
IF v_Enemy_Health < 0 THEN dbms_output.put_line (v_Enemy || 'Has Fainted. ' || v_Character || 'Wins!'); EXIT;
END IF;
v_Character_Health := v_Character_Health - v_Enemy_Attack;
dbms_output.put_line (v_Enemy || ' Hits ' || v_Character || ' for ' || v_Enemy_Attack || ' Damage' );
dbms_output.put_line (v_Character || ' Has ' || v_Character_Health || ' Health Remaining' || v_nl);
IF v_Character_Health < 0 THEN dbms_output.put_line (v_Character || 'Has Fainted. ' || v_Enemy || 'Wins!'); EXIT;
END IF;
END LOOP;
END;
/

String Replace a joined SQL SELECT statement

I'm wondering if it is possibly to complete a string replace on a joined SQL statement. For example, my query is:
SELECT (SITE_NAME || ', ' || LOT_NUMBER || ' ' || UNIT_TYPE || ' ' || LEVEL_NUMBER
|| ' ' || UNIT_NUMBER || ' ' || ROAD_NUMBER_1 || ' ' || ROAD_NUMBER_2 || ' ' || ROAD_NAME
|| ' ' || ROAD_TYPE || ' ' || ROAD_SUFFIX || ', ' || SUBURB || ', ' || STATE) AS address
FROM ADDRESS_LOOKUP_TOOL
WHERE ADD_ID = :P1_ADD_ID;
This statement works perfectly.... providing every single address field is populated. If only some sections are populated (i.e. there is no site name, or road suffix), there are additional commas or spaces.
Here is an example of a good select:
House of Dom, Lot 1 Suite 4 4D 119 Fake St South, Domtopia, QLD
Here is an example of a flawed select:
, Lot 1 Suite 4 4D 119 Fake St , Domtopia, QLD
Is it possibly to do a string replace on the alias where I could say, for example replace(address, ' ,', ',') (Where "space comma" just becomes "comma"), or is there a better way I should be structuring my select to pick this up in one go?
An additional note: This is all being completed with in Oracle's Application Express (ApEx) if this makes a difference.
I am very new to SQL, so I apologise in advance if I ask any basic follow up questions!
Thank you!
Dominic
You don't need to do it on the alias. Just do it on the expression itself.
SELECT REPLACE(
(SITE_NAME || ', ' || LOT_NUMBER || ' ' || UNIT_TYPE || ' ' || LEVEL_NUMBER
|| ' ' || UNIT_NUMBER || ' ' || ROAD_NUMBER_1 || ' ' || ROAD_NUMBER_2 || ' ' || ROAD_NAME
|| ' ' || ROAD_TYPE || ' ' || ROAD_SUFFIX || ', ' || SUBURB || ', ' || STATE),
' ,', ',') AS address
FROM ADDRESS_LOOKUP_TOOL
WHERE ADD_ID = :P1_ADD_ID;

Oracle PL/SQL cursor update

I'm using oracle. My SQL skills are very bad, I want to update information from a query that I have obtained through the use of a cursor, I've read about using the WHERE CURRENT OF statement, but I don't see how that can fit into my current code. Does anyone mind lending a helping hand? I want to allow a calling program to update a row in the cursor (I want to update the race location) returned by the query in my current code. Here's my code so far:
DECLARE
l_race_rec race%rowtype;
CURSOR Query1
IS
SELECT *
FROM RACE
WHERE Race_Time='22-SEP-14 12.00.00.000000000';
BEGIN
OPEN Query1;
LOOP
FETCH query1 INTO l_race_rec;
EXIT WHEN query1%notfound;
dbms_output.put_line( l_race_rec.raceid || ', ' || l_race_rec.race_location || ', ' ||
l_race_rec.race_type || ', ' || l_race_rec.race_time || ', ' || l_race_rec.sex || ', ' ||
l_race_rec.minage || ', ' || l_race_rec.maxage );
END LOOP;
CLOSE Query1;
END;
Here's an example to get you going:
DECLARE
l_race_rec race%rowtype;
CURSOR Query1 IS
SELECT *
FROM RACE
WHERE Race_Time = '22-SEP-14 12.00.00.000000000';
nSome_value NUMBER := 42;
BEGIN
OPEN Query1;
LOOP
FETCH query1 INTO l_race_rec;
EXIT WHEN query1%notfound;
dbms_output.put_line(l_race_rec.raceid || ', ' ||
l_race_rec.race_location || ', ' ||
l_race_rec.race_type || ', ' ||
l_race_rec.race_time || ', ' ||
l_race_rec.sex || ', ' ||
l_race_rec.minage || ', ' ||
l_race_rec.maxage );
UPDATE RACE
SET SOME_FIELD = nSome_value
WHERE CURRENT OF QUERY1;
END LOOP;
CLOSE Query1;
END;
Share and enjoy.
Why don't you use a cursor for loop.
...
for row in query1
loop
dbms_output.put_line(row.raceid || ', ' ||
row.race_location || ', ' ||
row.race_type || ', ' ||
row.race_time || ', ' ||
row.sex || ', ' ||
row.minage || ', ' ||
row.maxage );
UPDATE RACE
SET SOME_FIELD = nSome_value
WHERE CURRENT OF QUERY1;
end loop;
...
In this way there no need to open and to close a cursor.
Keep in mind that a cursor for loop works better for a cursor with more than 1 row as result.
Good luck.

PLSQL : Dynamic table record holder

If I want to fetch records from a table (table name is dynamic from input), how to define the record holder or how to fetch the data from this defined table? p_table_name%rowtype will not complie because p_table_name is a parameter, not a table name.
PROCEDURE do_scan(p_table_name IN VARCHAR2
,p_min_num IN NUMBER
,p_time_range IN NUMBER
,p_problem_desc OUT
,p_result_code OUT)
IS
TYPE ObjCurTyp IS REF CURSOR;
v_obj_cursor ObjCurTyp;
v_obj_record ???????(p_table_name%rowtype)
BEGIN
v_stmt_str := 'Select * from :t where date_started > TRUNC(SYSDATE-3)';
OPEN v_obj_cursor FOR v_stmt_str USING p_table_name;
LOOP
FETCH v_obj_cursor INTO v_obj_record;
EXIT WHEN v_obj_cursor %NOTFOUND;
END LOOP;
END do_scan;
You can put that code as a dynamic PL/SQL block within an EXECUTE IMMEDIATE statement.
PROCEDURE do_scan
(
p_table_name IN VARCHAR2
p_min_num IN NUMBER
p_time_range IN NUMBER
p_problem_desc OUT
p_result_code OUT
)
IS
BEGIN
EXECUTE IMMEDIATE
'DECLARE ' ||
' TYPE ObjCurTyp IS REF CURSOR; ' ||
' v_obj_cursor ObjCurTyp; ' ||
' v_obj_record ' || p_table_name || '%rowtype; '||
'BEGIN ' ||
' v_stmt_str := ''Select * from :t where ' ||
' date_started > TRUNC(SYSDATE-3)''; ' ||
' OPEN v_obj_cursor ' ||
' FOR v_stmt_str USING ' ||
p_table_name || '; ' ||
' LOOP ' ||
' FETCH v_obj_cursor INTO v_obj_record; ' ||
' EXIT WHEN v_obj_cursor %NOTFOUND; ' ||
' END LOOP; ' ||
'END;';
END do_scan;
Regards,
Dariyoosh