How to get the actual wrong value from a broken query? - sql

I have a very long query for insert, it gives me a "ORA-01722: invalid number" error, which is pretty simple thing usually. But this time i need to know what IN FACT value is wrong.
How do I do that?
I used construction
BEGIN
--longest spaghetti ever
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error: '||sqlerrm);
END;
But it only gives me that damn error code and nothing more.

If you work on 10g or above, you can use DBMS_UTILITY.FORMAT_ERROR_STACK. It will return the full error message. With this, you can get the line number that you get error and you can zoom right in on the problem.
EXCEPTION
WHEN OTHERS THEN
my_putline (
DBMS_UTILITY.FORMAT_ERROR_STACK);
END;

Related

Can't use LOOP PostgreSQL

I'm facing an issue from yesterday and I can't understand why my SQL is not working..
This may be a simple error since i'm a beginner in SQL but I can't find where it is.
Here is what I try to do:
CREATE FUNCTION test() RETURN integer AS $$
BEGIN
FOR i IN 1..5 LOOP
SELECT * from result WHERE id=i;
end loop;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
This is just a simple loop as I can find in the documentation but I have this error:
Error report -
ERROR: syntax error at or near "RETURN" (this is the first RETURN statement in the function)
The database is in PostgreSQL and the version is 9.4.5
Why it's not working ?
There are several problems, apart from the fact that the function isn't doing anything useful:
It must be RETURNS integer, not RETURN integer.
That't what causes the error.
The SELECT has no destination. Either add an INTO clause or discard the result with
PERFORM * from result WHERE id=i;
You should indent the code correctly, so that you can read and understand it.

SQL Delphi "Parameter 'Subject' not found"

I have recently started to learn how to code in Delphi since moving from Python to do a project. I can't seem to find a fix to this issue. I have searched online for a couple of hours now and none of the 'fixes' seem to be working. I have tried using 'Query.ExecSQL', I have tried breaking the code up into segments, I have tried to assign edtSubject.Text to a variable and doing it that way, among a handful of other 'solutions' that haven't fixed the issue. I am really struggling with this and need a way to fix it that works quick, here is my code:
Query := TADOQuery.Create(Self);
Query.Connection := ADOConnection;
Query.SQL.Add('INSERT INTO tbl_RFI (Subject) VALUES (:Subject)');
Query.Parameters.ParamByName('Subject').Value := edtSubject.Text;
Query.ExecSQL;
I really hope that someone can help me with this,
Thanks.
Just add Query.ParamCheck := true before setting the SQl Text and it should be fine
Despite what others say I have had this same thing happen from time to time over the years in my production code.
Parameter 'ParameterName' not found
Always with ADO objects that were created in code. The best fix that I have found was here http://edn.embarcadero.com/article/20420
Basically just force the ADO object to reparse the parameters before you reference them.
EDIT: Thanks to Ken's feedback I have added a test first to check if the parameter exists before calling ParseSQL, thereby conserving the execution plan for the 99.9% of the time.
with TADODataSet.Create(nil) do
try
Connection := MyADOConnection;
CommandText := 'SELECT Foo ' +
'FROM FooBar ' +
'WHERE Bar = :Bar ';
if Parameters.FindParam('Bar') = nil then
Parameters.ParseSQL(CommandText, True); {<- THIS IS THE FIX }
Parameters.ParamByName('Bar').Value := 'value';
Open;
finally
Free;
end;
Since adding the ParseSQL I haven't had the problem.
Late reply I know, but I just went through the same situation, so in case this helps someone else. And it happens at random, "parameter not found" during in my case a tadocommand. Program errors out, restart doing exactly same sequence of events and works fine. Load up compiler, step through and works just fine. Set a breakpoint, and I can see the parameter not defined. But again, it's not every time, it's kind of random.
So it feels like some type of timing issue. I tried the ParseSQL command, and that actually makes it error out every time with a different error. I think the command text was getting cropped but did not investigate this. (it's a fairly long command)
Anyway, it seems I was able to fix this by adding in an application.processmessages after my tadocommand is created and sql text assigned.

THROW or RAISERROR for specific non-user defined error codes

I'm trying to test some code that traps a specific error code in SQL server. The error code is 7886.
When I try to THROW, I get:
Error number 7886 in the THROW statement is outside the valid range. Specify an error number in the valid range of 50000 to 2147483647.
When I try to RAISERROR, I get:
Error number 7886 is invalid. The number must be from 13000 through 2147483647 and it cannot be 50000.
Is there any way to raise an arbitrary error like this without actually setting up the situation to cause the error in the first place?
As said in the comments of the original question, this is impossible to do in SQL server.
:(

PL/SQL Validate/Insert/Update Status - retval vs. exception

I'm always looking to improve and applying best practices. I read quite a bit about refactoring in the last weeks. I have to work with a lot of awful code and I produced some not so nice stuff too but I'm trying to change that. Thats no problem for most languages but I'm pretty new to PL/SQL so I just copied the style of the already written code.
After reading some tutorials I realized that a lot of our code is pretty much more C style code using retval instead exceptions etc.
We have a lot of functions like open cursor, loop through it, validate the data, trim it or make some string manipulation and insert it into another table, update the status etc. I wonder what a best practice solution would look like on something like this. Atm most functions look like this:
LOOP
FETCH C_ABC INTO R_ABC;
EXIT WHEN C_ABC%NOTFOUND OR C_ABC%NOTFOUND IS NULL;
SAVEPOINT SAVE_LOOP;
retval := plausibilty_check(r_ABC);
IF (retval = STATUS_OK) THEN
retval := convert_ABC_TO_XYZ(r_ABC, r_XYZ);
END IF;
IF (retval = STATUS_OK) THEN
retval := insert_XYZ(r_XYZ);
END IF;
retval := update_ABC(r_ABC.PK_Id, retval);
END LOOP;
If i was using exceptions I guess I had to raise them inside the functions so I can handle them in the main function, if not everyone would have to crawl to every sub function to understand the program and where the updates happen etc. So I guess I would have to use another PL/SQL block inside the loop? Like:
LOOP
FETCH C_ABC INTO R_ABC;
EXIT WHEN C_ABC%NOTFOUND OR C_ABC%NOTFOUND IS NULL;
SAVEPOINT SAVE_LOOP;
BEGIN
plausibilty_check(r_ABC);
convert_ABC_TO_XYZ(r_ABC, r_XYZ);
insert_XYZ(r_XYZ);
update_ABC(r_ABC.PK_Id, STATUS_OK);
EXCEPTION
WHEN ERROR_CODE_XYZ THEN
update_ABC(r_ABC.PK_Id, ERROR_CODE_XYZ);
END
END LOOP;
I guess that function handles a pretty common problem but I still havn't found any tutorial covering something like this. Maybe someone more experienced with PL/SQL might gimme a hint what a best practice on a task like that would look like.
I like to use exceptions to jump out of a block of code if an exceptional event (e.g. an error) occurs.
The problem with the "retval" method of detecting error conditions is that it introduces a second layer of semantics on what a function is and for.
In principle, a function should be used to perform a calculation and return a result; in this sense, a function doesn't do anything, i.e. it makes no changes to any state - it merely returns a value.
If it cannot for some reason calculate that value, that would be an exceptional circumstance, so I'd want the function to raise an exception so that the calling program will not blindly continue on its merry way, thinking it got a valid value from the function.
On the other hand, a procedure is a method by which action is done - something is changed, something is validated, or something is sent. The normal expected path is that the procedure is executed, it does its thing, then it finishes. If an error occurs, I want it to raise an exception so that the calling program will not blindly continue thinking that the procedure has successfully done its thing.
Thus, the original intent of the fundamental difference between "procedures" and "functions" is preserved.
In languages like C, there are no procedures - everything is a function in a sense (even functions that return "void") - but in addition, there is no real concept of an "exception" - so these semantics don't apply. It's for this reason that the C style of returning an error/success flag don't translate well into languages like PL/SQL.
In your example, I'd consider doing it something like this:
BEGIN
LOOP
FETCH c_ABC INTO r_ABC;
EXIT WHEN c_ABC%NOTFOUND;
IF record_is_plausible(r_ABC) THEN
r_XYZ := convert_ABC_TO_XYZ(r_ABC);
insert_or_update_XYZ(r_XYZ);
ELSE
update_as_implausible(r_ABC);
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
-- log the error or something, then:
RAISE;
END;
So where the semantics of the operation is doing some validation or something, and returning a result, I converted plausibilty_check into a function record_is_plausible that returns a boolean.
I'd pull the call to update_ABC out of the BEGIN block and make it common at the bottom of the loop, as in:
DECLARE
nFinal_status NUMBER;
BEGIN
LOOP
FETCH C_ABC INTO R_ABC;
EXIT WHEN C_ABC%NOTFOUND OR C_ABC%NOTFOUND IS NULL;
SAVEPOINT SAVE_LOOP;
nFinal_status := nSTATUS_OK;
BEGIN
plausibilty_check(r_ABC);
convert_ABC_TO_XYZ(r_ABC, r_XYZ);
insert_XYZ(r_XYZ);
EXCEPTION
WHEN excpERROR_CODE_XYZ THEN
nFinal_status := nERROR_CODE_XYZ;
END;
update_ABC(r_ABC.PK_Id, nFinal_status);
END LOOP;
END;
You might want to have each of the procedures throw its own exception so you could more easily identify where the issue(s) are coming from - or use different exceptions/error codes for each possible issue (for example, the plausibility check might raise different exceptions depending on what implausible condition it found). However, in my experience plausibility checks will often uncover multiple conditions (if the data's bad it's often really bad :-), so it might be nice to tabularize the errors and relate them to the base ABC data through a foreign key, thus allowing each individual error to be identified with just one pass through the data. Then the 'status' field on ABC becomes moot; you either have errors associated with the ABC row or you don't. If errors exist, do whatever is needed. If no errors, proceed with 'normal' processing.
Just a thought.
Share and enjoy.

Does a sqlcode value other than zero always indicate an error condition in pl/sql

if sqlcode is not 0 (in oracle plsql) then always throw an exception?
makes sense to ask for SQLCODE if not is an exepcion.
Example:
if (sqlcode = 0) ...
IF you are asking if you should always throw an exception if SQLCODE is not zero, not always.
Here is a list of some SQLCodes. As you can see, some SQLCodes ( such as 100 ) do not necessarily mean that there is an error.
Hope this helps
Looks like you're mixing error checking and exception handling. SQLCODE, by definition, only makes sense inside an exception handler.
Raising exceptions happens automatically. Unless your code is catching exceptions and returning them instead of re-raising them. Which kind of ruins
the whole point of exception handling.