so i had a problem with my page and i after i compared it with other similar pages i noticed it's missing a pre-rendering -> after header -> process which basically reloads data automatically with the item value that i sent from the previous page. the process is called automatic row fetch [lefacy].
i tried to create it for that page but it always show an error when i try to load it.
any tips what i might be missing
and i get this error message
ORA-06550: line 1, column 22: PL/SQL: ORA-00936: missing expression
Contact your application administrator. Details about this incident are available via debug id "353666".
Technical Info (only visible for developers)
error_statement:
begin begin select into from "CONTRAT" where "ID_CONTRAT" = :p_rowid; end;
end;
Your select clause is incomplete. You should inform something on select and into.
example:
declare
v_name varchar2(50);
begin
select NAME
into v_name
from EMPLOYEE;
end;
Related
I'm trying to make an exception with RAISE in PL / SQL. I did the script but when I want to run it does not show me one of the two messages and it just gives me 'anonymous block completed'.
Accept cititor prompt 'Introduceti un cititor';
DECLARE data_la_limita EXCEPTION; data_returnare varchar(10);
--cititor varchar(10);
BEGIN
SELECT s.data_dereturnat INTO data_returnare FROM fisa_imprumuturi s left join legitimatii s1
on s1.nrlegitimatie = s.nr_legitimatie left
join cititori s2 on s2.codcititor = s1.codcititor
WHERE s2.numecititor like '%&cititor%'; IF (data_returnare > sysdate ) THEN
RAISE data_la_limita;
END IF;
EXCEPTION
WHEN data_la_limita THEN
DBMS_OUTPUT.PUT_LINE('Cititorul a trecut peste data returnarii!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Cititorul trebuie sa returneze la data: ' || data_returnare); END;
I tried to replace sysdate with a date manually ('01-May-2019') but is not working.
I'm trying to make an exception with RAISE in PL / SQL ... but when I want to run it does not show me one of the two messages
You're not seeing the messages because you are running your program in an environment which doesn't show DBMS_OUTPUT. You have coded an EXCEPTION handler which suppresses your exceptions and does not re-raise them. This is bad practice because DBMS_OUTPUT is not a mechanism for propagating exceptions: when output is suppressed or the program runs as an autonomous background routine (which is the main use of PL/SQL) there is no way to tell that the program failed.
You could enable SEVEROUTPUT (in SQL*Plus) or configure a DBMS_OUTPUT tab (in an IDE like SQL Developer). Doing this means you would see the messages next time your program runs.
But it would be better just to raise exceptions and let the calling program handle them. Given that, you should probably re-write your program something like this:
Accept cititor prompt 'Introduceti un cititor';
DECLARE
data_la_limita EXCEPTION;
data_returnare varchar(10);
--cititor varchar(10);
BEGIN
SELECT s.data_dereturnat
INTO data_returnare
FROM fisa_imprumuturi s
left join legitimatii s1 on s1.nrlegitimatie = s.nr_legitimatie left
join cititori s2 on s2.codcititor = s1.codcititor
WHERE s2.numecititor like '%&cititor%';
IF (data_returnare > sysdate ) THEN
RAISE data_la_limita;
END IF;
EXCEPTION
WHEN data_la_limita THEN
raise_application_error(-20000, 'Cititorul a trecut peste data returnarii!');
END;
It is better not to code a WHEN OTHERS handler unless we're logging the message. Even then we should execute a RAISE to pass the actual error instead of an unhelpful generic message. The calling program needs to know what went wrong so it can make the correct decision about what to do next (e.g. ignore and continue, abort and re-raise, something else).
In SQL Developer, when running some PL/SQL, when the procedure is completed, the message 'PL/SQL procedure successfully completed.' is returned.
The PL/SQL that is run may return error messages to the user if the operation could not be completed for any reason through DBMS_OUTPUT.PUT_LINE, however, the user will also see 'PL/SQL procedure successfully completed.', which could be misleading (especially if the Script Output window is small enough that the DBMS_OUTPUT is not visible).
Is there any way to have the DBMS_OUTPUT return what it should whilst also having the script not return 'PL/SQL procedure successfully completed.'?
If not, are there any alternatives in SQL Developer that I may be unaware of to provide instant personalised feedback to the user?
declare
testex exception;
begin
if 1=1 then
raise testex;
end if;
exception when testex then
dbms_output.put_line('Error msg');
end;
Below code works in my end. Did you try to run your code like below?
Copied text from a website to explain the SET FEEDBACK OFF command.
Source link: https://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12040.htm
SET FEED[BACK] {6 | n | ON | OFF} -
Displays the number of records returned by a script when a script selects at least n records.
ON or OFF turns this display on or off. Turning feedback ON sets n to 1. Setting feedback to zero is equivalent to turning it OFF.
SET FEEDBACK OFF also turns off the statement confirmation messages such as 'Table created' and 'PL/SQL procedure successfully completed' that are displayed after successful SQL or PL/SQL statements.
Add a RAISE statement in the error handler to re-raise the exception so that any outer handler can deal with it:
declare
testex exception;
begin
if 1=1 then
raise testex;
end if;
exception when testex then
dbms_output.put_line('Error msg');
RAISE; -- re-raise the exception to an outer handler
end;
Best of luck.
You have coded it explicitly to complete successfully in the event of a testex exception. The code says: if this happens, then print a message and end. If you want it to actually fail then it needs to raise an exception.
I would just use something like this:
begin
if 1=1 then
raise_application_error(-20000, 'Bananas are not available on a Tuesday');
end if;
end;
/
begin
*
ERROR at line 1:
ORA-20000: Bananas are not available on a Tuesday
ORA-06512: at line 3
This will cause an actual error, rather than just printing out a message that happens to talk about an error, allowing you to control deployments and build scripts etc.
It will also roll back any uncommitted transactions within the block, which your current approach does not, and it will show the actual line number.
I have a series of update statements that I need to use in my Oracle package. It's rare but there may be an occasional and unavoidable user error that would result in one of the update statements throwing a "Single row sub-query returns one or more rows" Error.
I've been looking into exception handling for oracle PL/SQl and I'm a bit stuck on how and what to use to catch this exception so the package doesn't crash.
I know of the pre-built "Too Many Rows" exception clause that exists but everything I read seems to say it is used for improper insert statements.
Can I use this as my exception? Or do I need to build my own exception clause. I've never built one myself before and have only a rough idea on where to put everything needed for it.
The following code is basically how the updates are set up in this particular procedure
but for the sake of brevity I'm only using a bare bones example of how it looks.
INSERT INTO TempTable... --(Initial insert statement)
UPDATE TempTable t SET t.Row_one = (SELECT (Statement_One))
WHERE T.Row_One is NULL
UPDATE TempTable t SET t.Row_one = (SELECT (Statement_Two))
WHERE T.Row_One is NULL
UPDATE TempTable t SET t.Row_one = (SELECT (Statement_Three))
WHERE T.Row_One is NULL
-- Does the exception clause start here?
EXCEPTION
WHEN TOO_MANY_ROWS THEN
(What do I tell the Procedure to do here, what am I able to tell it to do?)
--end of updates that need the exception handling
-- more insert statements into other tables based on data from the preceding Temp Table
END;
Will this work or do I need to build a custom exception?
Thanks in advance.
First, the TOO_MANY_ROWS exception will not catch the case where your select statements return multiple rows. The TOO_MANY_ROWS exception is for ORA-01422 when you issue a SELECT .. INTO statement that returns more than one row. The exception you'll encounter in your case is ORA-01427, Single row subquery returns more than one row.
If you want to handle this specific error in your procedure, use the EXCEPTION_INIT pragma to associate an exception name with the error:
too_many_values EXCEPTION;
PRAGMA EXCEPTION_INIT(too_many_values, -1427);
Then you can reference this name in your exception handler:
EXCEPTION
WHEN TOO_MANY_VALUES THEN
{perform your handler here}
What you put in the handler depends on what your procedure does. Many times you'll want to return some sort of error code/message to your caller:
PROCEDURE my_proc(p_one VARCHAR2, p_err OUT VARCHAR2) IS
too_many_values EXCEPTION;
PRAGMA EXCEPTION_INIT(too_many_values, -1427);
BEGIN
...
EXCEPTION
WHEN TOO_MANY_VALUES THEN
p_err := 'More than one value available to assign in the update';
RAISE; -- re-raise the exception for the caller
WHEN OTHERS THEN
p_err := SQLERRM; -- return the oracle message for the unexpected error
RAISE;
END;
Another approach is to skip the specific exception handlers and return generic oracle messages in the WHEN OTHERS handler:
EXCEPTION
WHEN OTHERS THEN
p_err := SQLERRM;
END;
The advantage with the first approach is you can customize your messages to be more end-user friendly when the output from the process is fed directly back to the user. The advantage with the latter approach is there is less coding involved. Error handling is an important and often skimped on aspect of any application.
The documentation from Oracle is here.
EDIT:
If this is a package, and you want to avoid passing a long chain of error variables through a series of procedure calls, you could declare an error variable with package scope, set it when the error is encountered, and RAISE the error again.
PACKAGE BODY my_pkg is
g_err VARCHAR2(256);
PROCEDURE procx(... , p_err OUT VARCHAR2) IS...
...
proc_y(p1);
EXCEPTION
WHEN OTHERS THEN
p_err := NVL(g_err, SQLERRM);
END;
PROCEDURE proc_y(p1 VARCHAR2) IS
...
proc_z(p2);
END;
PROCEDURE proc_z(p2 VARCHAR2) IS
too_many_values EXCEPTION;
PRAGMA EXCEPTION_INIT(too_many_values, -1427);
BEGIN
....
EXCEPTION
WHEN TOO_MANY_VALUES THEN
g_err := 'More than one value available to assign in the update';
RAISE; -- re-raise the exception for the caller
END;
When the exception is raised in proc_z, it is handled and then raised again. It propagates back through proc_y (no handler there) and then gets returned to the user in proc_x. Errors not set in the global g_err get the generic Oracle error message. This avoids having to pass the initial error parameter throughout the package.
This has to be provider related in some way because it works fine on my dev box but doesn't work on another dev box.
Here is the error I'm getting on the non-working dev box:
ORA-00604: error occurred at recursive SQL level 1
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 26
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'LISTAVAILSUBMISSIONS'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
Here is the Oracle Procedure:
Procedure ListAvailSubmissions (avail_submission in out rc_avail_submission)
is
Begin
open avail_submission for
select submission_id from nais_submissions
where condition = 'ONLINE'
and status in ('ACTIVE','LOGGED')
order by submission_id desc;
Exception
When no_data_found then
v_output := utl_file.fopen (v_errdir, v_errLog, 'a');
utl_file.put_line(v_output, to_char(sysdate,'HH24:MI:SS')||'-'||'ListAvailSubmission:Sub_id: No Data Found');
utl_file.fclose(v_output);
When others then
v_error_code := sqlcode;
v_error_message := substr (sqlerrm, 1, 300);
v_output := utl_file.fopen (v_errdir, v_errLog, 'a');
utl_file.put_line(v_output, to_char(sysdate,'HH24:MI:SS')||'-'||'ListAvailSubmission:Sub_id:'|| v_error_code ||':'|| v_error_message);
utl_file.fclose(v_output);
End ListAvailSubmissions;
As you can see, the only parameter is the return parameter which is the resulting recordset
The call from VB is pretty simple.
Public Function GetTestRequests() As ADODB.Recordset
Dim rsADO As New ADODB.Recordset
Dim cmdCommand As New ADODB.Command
Set cmdCommand.ActiveConnection = cnnADO //Ive already verified the connection is good
cmdCommand.CommandText = "ListAvailSubmissions"
Set rsADO = cmdCommand.Execute(, , adCmdStoredProc)
Set GetTestRequests = rsADO
End Function
The frustrating part is the it works on one machine and not another. I'm using msdaora.1 as the provider and I've verified both machines have the same MDAC version using MS CompChecker tool. One thing I did discover is that if I switch the working machine to using OraOLEDB instead of msdaora.1, it will then throw the same error. Based on that I'm starting to think that the non-working machine is exhibiting the correct behavior and that I need to fix the code.
I have done quite a bit of research and I'm thinking it has to do with the in out parameter and trying to set an ADODB.Recordset equal to the parameter. I tried changing the parameter to out only but that didn't help, still got the same error.
Any help is appreciated, this error is driving me nuts.
I think one of the strings in your table exceeds the OLEDB string limit. This limit is defined differently for different drivers -- so you see one driver giving error and another works. This limit, I believe, can also be configured on a machine-by-machine basis, thus you have one machine working and one doesn't.
Check if any string in your result set is longer than, say, 256 characters or something really long. Then omit that record from your result set to see if it works.
I'm having difficulty debugging triggers in Oracle. Currently I'm using Oracle's Sql Developer tool.
To test a trigger I write inserts or deletes in a test window but I can't see what is happening inside the trigger. I would like to step through the trigger and see what is happening as the trigger fires. Is there any way to use select statements to display variable values inside the triggers?
Firstly, don't "start from here", or more specifically, don't use triggers. Triggers are going to force switching to row-level processing if the triggers are going to fire for each row. It's better to put the logic in a stored procedure which you call. You've then got a start (where you validate inputs) and an end and a logic path all the way through. Stored procedures are a lot easier to debug as you follow one path.
Second, never test for an error you don't know how to handle. If you don't catch it, it bubbles up to the client who gets an error report saying what went wrong (error message) and where (i.e. the error/call stack). If you try to catch it, you have to know what to do with it (and if you don't know the tendency is to ignore it - which is BAD).
Finally, you can't readily see each 'layer' of a select. The explain plan will generally tell you how its going about things. v$session_longops MAY indicate what it is currently doing. The current wait event MAY give clues as to what table/block/row it is currently working on.
A rough-and-ready simple method if you must debug triggers is to use DBMS_OUTPUT.
e.g.
SQL> CREATE OR REPLACE TRIGGER mytrigger
BEFORE UPDATE ON mytable
FOR EACH ROW
...
BEGIN
DBMS_OUTPUT.put_line('mytrigger STARTING');
... do some logic ...
DBMS_OUTPUT.put_line('old=' || :OLD.mycolumn);
DBMS_OUTPUT.put_line('new=' || :NEW.mycolumn);
DBMS_OUTPUT.put_line('mytrigger FINISHED');
END;
/
SQL> SET SERVEROUT ON
SQL> UPDATE mytable SET mycolumn = mycolumn + 1;
2 rows updated.
mytrigger STARTING
old=10
new=11
mytrigger FINISHED
mytrigger STARTING
old=20
new=21
mytrigger FINISHED
Application
I use a program from Quest called TOAD available at www.quest.com/toad/toad-for-oracle.aspx.
As mentioned above, DBMS_OUTPUT is very handy. In your editor, make sure you enable the Output window.
PL/SQL works on "blocks" of code and you can catch it with an EXCEPTION keyword.
(Please forgive my formatting, not sure how to format for web)
DECLARE
C_DATE_FORMAT VARCHAR2(20) := 'DD-Mon-YYYY';
C_TIME_FORMAT VARCHAR2(20) := 'HH24:MI:SS';
C_NOT_IMPLEMENTED_CODE CONSTANT NUMBER(5) := -20200;
C_NOT_IMPLEMENTED_MESSAGE CONSTANT VARCHAR2(255) := 'Not implemented';
not_implemented EXCEPTION; -- user defined exception
BEGIN
--RAISE not_implemented; -- raise user defined exception
RAISE_APPLICATION_ERROR(C_NOT_IMPLEMENTED_CODE, C_NOT_IMPLEMENTED_MESSAGE); -- user defined exception
EXCEPTION -- exception block
WHEN not_implemented THEN -- catch not_implemented exception
DBMS_OUTPUT.PUT_LINE('Error: Not implemented');
WHEN OTHERS THEN -- catch all other exceptions
DBMS_OUTPUT.PUT_LINE('Error occured.');
DBMS_OUTPUT.PUT_LINE('Date: ' || TO_CHAR(SYSDATE, C_DATE_FORMAT));
DBMS_OUTPUT.PUT_LINE('Time: ' || TO_CHAR(SYSDATE, C_TIME_FORMAT));
DBMS_OUTPUT.PUT_LINE('Error code: ' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('Error message: ' || SQLERRM); --deal with error
RAISE; -- raise to calling object
END;
Follow below steps to DEBUG trigger in Oracle PL/SQL
Open your trigger using Edit option. Set breakpoint by clicking on line number (See below).
Open Test Window as shown below.
Write Insert/Update query for your table. (Note: Your trigger could be set on update/insert or both)
Click Start debugger button.
As soon as value will be updated in your Table. Debugger will take you to trigger. Where you can continue your debugging.