I've got a PL/SQL-Block which looks like this:
declare
L_Count number := 10;
begin
if L_Count > 0then
dbms_output.put_line('l_Count > 0');
else
dbms_output.put_line('l_Count <= 0');
end if;
exception
when others then
dbms_output.put_line('exception occurred');
end;
Note the fourth line containing 0then instead of 0 then.
Using PL/SQL-Developer, I can execute this block as an SQL statement, which actually outputs l_Count > 0. Using a "Program Window" and compiling this, PL/SQL-Developer says the following error:
Unable to perform operation due to errors in source code
How can this statement execute but not compile?
Thank you for your hints!
The behavior is not what I would expect either. However, both the PL/SQL Developer SQL Window and Command Window modes execute this consistently with how SQL*Plus behaves. So, this is either:
Not a bug, or
An Oracle bug but not an Allround Automations bug.
Execution and compilation are two separate things. The code block is an anonynous block and it cannot be compiled. However you can execute the block. Execution would show you l_Count > 0.
Thanks,
Aditya
Related
I am writing a script where the output from one procedure is needed for multiple later procedures. So, I need bind variables, not substitution variables. But, whenever the variable is used, it is cleared. That makes it impossible to use a variable's value more than once. The exact same script works in SQL*Plus. I have made a shortened script below that demonstrates the problem.
Is this a setting that can be changed in SQL Developer? Is this a bug? In my case, I am using SQL Developer version 4.1.5.21.78.
var x varchar2(1)
var y varchar2(1)
print x
print y
exec :x := 'Z';
exec :y := 'Z';
print x
print y
exec :x := :y;
-- Why did that last line clear y?
print x
print y
output
X
------
Y
------
PL/SQL procedure successfully completed.
PL/SQL procedure successfully completed.
X
-
Z
Y
-
Z
PL/SQL procedure successfully completed.
Y
-
X
-
Z
This seems to be a bug in 4.1.5, and possibly other versions, that has been fixed by version 4.2.0.17.
exec is just a wrapper for an anonymous block, but using an explicit block instead also shows the problem:
begin
:x := :y;
end;
/
I'm pretty sure I've seen this reported before, but the only example I can find is this question; as that notes you can work around it by reassigning the value to itself:
begin
:x := :y;
:y := :y;
end;
/
or slightly less readably:
exec :x := :y; :y := :y;
It certainly appears to be a bug, but as it's fixed in the current release, upgrading seems like a sensible way to resolve it. Otherwise you'd need to raise a service request to Oracle - though I suspect they'd advise to upgrade anyway.
(I may have been thinking all the way back to this, but that seems to be a different problem as that example looks OK in 4.1.5. I can't see any bug reports in My Oracle Support, for either issues; but they aren't always published.)
While executing scripts in SQLPlus I've encountered a problem:
script.sql contains the following lines
#some_pkg.pks
#some_pkg.pkb
drop package some_pkg;
/
After calling
> sqlplus user/password#dbname #script.sql
the following messages are in console:
Package created.
Package body created.
Package dropped.
drop package some_pkg;
*
ERROR at line 1:
ORA-04043: object SOME_PKG does not exist
Please, explain what's happening here. Looks like the package is being dropped twice. Is it possible to avoid the error?
The rules of SQLplus command execution basically are:
Execute the current text when you encounter a semi-colon. Thus if a line doesn't end with a semi-colon, the current text continues to be collected.
If you encounter DECLARE or BEGIN, collect all the text and do not execute on semi-colons
If you encounter a slash (/), execute the collected text.
So what happens in your cases is, that both the semi-colon and the slash execute the DROP statements.
To fix it, remove the slash.
You only need the slash if you have a block of PL/SQL, which always with an END statement. Use semicolons for everything else.
Note: the above rules are simplified. It's more complex in practice.
Some examples will help to understand rules:
Below code will be executed once
begin
dbms_output.put_line('executed');
end;
/
Below code will not execute (missing semicolon)
begin
dbms_output.put_line('executed')
end
/
Below code will be executed twice
begin
dbms_output.put_line('executed');
end;
/
/
Below code will be executed once
select 1 from dual
/
Below code will be executed once
select 1 from dual;
Below code will be executed twice
select 1 from dual;
/
This code compiles, but in TOAD it won't show the "hi wo" output
CREATE OR REPLACE PROCEDURE AdelTest IS
tmpVar NUMBER;
BEGIN
DBMS_OUTPUT.ENABLE(100: in INTEGER);
DBMS_OUTPUT.PUT_LINE('hi wo');
tmpVar := 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
--consider logging error then r-raise
RAISE;
END AdelTest;
How do I show the output(similar to how println shoots to console in Java ) ?
You need to enable DBMS Output. If working in the Editor right-click and choose DBMS Output off of the Desktop flyout menu. There's a button that is red if it's disabled. Click it and it will turn green. Then execute your code. Output will display there. If you are working outside of the Editor (in Schema Browser for instance) select DBMS Output off of the main Toad View menu. Enable your output there. Output will display in that window.
You can also view server output if for some reason DBMS output window is not getting enable. use QSR editor embedded within toad for oracle edition..
How to use
select the code in place
Editor > Execute SQL via QSR
have the set serveroutput on as first statement in QSR window and run..
now it will show output in window..
Hope it helps!!!
In the Editor right-click and choose DBMS Output off of the Desktop
flyout menu. There's a button that is red if it's disabled. Click it
and it will turn green. Then execute your code.
Need to enable the Automatically poll for output after execution under DBMS Output
DECLARE
v_text VARCHAR2(20); -- declare
BEGIN
v_text := 'Hello World'; --assign
dbms_output.Put_line(v_text); --display
END;
i have a tricky SQL Problem:
We have a huge SQL Script which installs our application on the DB server.
We want to skip the database installation if the latest update didn't change anything in the DB.
I have implemented following check, which is executed before the other SQL commands:
check_current_version_delta.sql:
DECLARE
v_deploy_version VARCHAR2(30) := '&db_deploy_version';
v_check BOOLEAN := FALSE;
BEGIN
DBMS_OUTPUT.PUT_LINE( '--------------------------------------------------------------------------------');
DBMS_OUTPUT.PUT_LINE( 'Check if we have a new DB version');
DBMS_OUTPUT.PUT_LINE( '--------------------------------------------------------------------------------');
FOR cu_version IN (SELECT version FROM &DB_CURRENT_USER..db_deployment WHERE version = v_deploy_version AND ROWNUM = 1) LOOP
v_check := TRUE;
END LOOP;
IF v_check THEN
RAISE_APPLICATION_ERROR( -20001, 'DB Version: '||v_deploy_version||' is already installed');
END IF;
END;
/
This is working very well but our installation team complains about the ORA-XXXXX Error in the log, because they have automated error checks this installation is marked as FAIL (though there was no actual error)
So now the actual problem:
I need to cancel the execution of the SQL without any errors in the LOG. Is this even possible?
Alternative would be to make the rest of the installation dependent on the outcome of the script above. But i'm not sure how to accomplish that.
Have you some suggestions on how to handle it the good way?
One possible way is to create three scripts: The first checks for the condition and either calls the second or the third. The second does the real job. The third is an empty dummy, to avoid the error message cause by calling a non-existent script
In code, it looks like this:
col SCRIPT1_COL new_val SCRIPT1
SELECT case
when version = '&db_deploy_version' then 'dummy.sql'
else 'upgrade_db.sql'
end as SCRIPT1_COL
FROM &DB_CURRENT_USER..db_deployment;
#&SCRIPT1
Alternatively, you could use the method shown above to load either a script "dummy.sql" that does nothing or a script "exit.sql" that just contains the exit command, and execute it before doing the real job.
Presumably you're already using whenever sqlerror so make it terminate when you raise that exception, and you're redirecting the output to your log file. If so you can just hide the text of the exception with set termout off:
whenever sqlerror exit success
set termout off
DECLARE
...
BEGIN
...
IF v_check THEN
RAISE_APPLICATION_ERROR( -20001,
'DB Version: '||v_deploy_version||' is already installed');
END IF;
END;
/
set termout on
whenever sqlerror exit failure
... the rest of your script
The script will stop if the exception is raised but produce no output. The success means anything that runs this won't decide it has errored independently of the log; the exit code from sqlplus will be zero.
You may be spooling to output instead; in which case just don't start the spool until after your check. Or if you have things before this that you do have to spool, turn the spool off and then on again afterwards with append.
As we know in MSSQL we can write below line to print some message
print 'Some Message';
How we can do same in Oracle as print not working with Oracle?
Use
DBMS_OUTPUT.put_line('Some Message');
To expand on #mhasan's answer and #AlexPoole's comment: assuming that you're executing your script using SQL*Plus you'll need to add the beginning of your script before the first DECLARE or BEGIN:
SET SERVEROUTPUT ON SIZE 1000000
SET LINESIZE 255
If you're using a tool other than SQL*Plus to run your script there will be different ways to view output written to DBMS_OUTPUT. For example, in PL/SQL Developer a "Test" window has a "DBMS Output" tab where text written to DBMS_OUTPUT can be viewed after the test script terminates.
Share and enjoy.