Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to 'SELECT INTO' when value doesn't exist

SELECT Value1 INTO lValue
FROM   Table1
WHERE  Field1 = lTempValue;

This works fine when the match is true. But if the match isn't true, I receive an error.

ORA-01403: no data found

Ideally, that's fine with me because I'm going to check that value next to see if it's above 0 and if it is, use that value in an insert query. I don't want to check for the value and then have to run the same query to retrieve it essentially, I want to do it in one query if possible, but I can't figure out how that is done.

If there's a value, then I want that value to go into lValue. If there is no value, then I want 0 to go into lValue. Anyone got any ideas? I've only done a quick google check, but it came up dry. Figured I'd post this while looking. Thanks for the help.

like image 976
XstreamINsanity Avatar asked Aug 22 '12 19:08

XstreamINsanity


People also ask

How do you handle no data found in SQL query?

When you are selecting INTO a variable and there are no records returned you should get a NO DATA FOUND error. I believe the correct way to write the above code would be to wrap the SELECT statement with it's own BEGIN/EXCEPTION/END block.

When a SELECT into statement does not return a row?

If the SELECT statement returns more than one row, Oracle will raise the TOO_MANY_ROWS exception. If the SELECT statement does not return any row, Oracle will raise the NO_DATA_FOUND exception.

How do you handle no data found exception in PL SQL?

Answer: To prevent the PLSQL code from dropping to the exception code when a record is not found, you'll have to perform a count first to determine the number of records that will be returned. For example: -- Check to make sure that at least one record is returned SELECT COUNT(1) INTO v_count FROM sales.

What is the difference between SELECT and SELECT into statement?

INSERT INTO SELECT vs SELECT INTO: Both the statements could be used to copy data from one table to another. But INSERT INTO SELECT could be used only if the target table exists whereas SELECT INTO statement could be used even if the target table doesn't exist as it creates the target table if it doesn't exist.


2 Answers

Normally, you'd simply catch the exception

BEGIN
  SELECT value1
    INTO lValue
    FROM table1
   WHERE field1 = lTempValue;
EXCEPTION
  WHEN no_data_found
  THEN
    lvalue := 0;
END;

You can write less code by using NVL and an aggregate function (either MIN or MAX) but that tends to be a bit less obvious (note, for example, that those answers had to get revised a couple of times). And it requires whoever comes after you to pause for a moment to understand what you are doing (and whether you are doing it correctly or not). A simple nested PL/SQL block is pretty common and pretty self-explanatory.

More than that, however, it doesn't hide bugs due to duplicate rows. If you happen to get two rows in table1 where field1 is lTempValue, catching just the no_data_found exception allows the unexpected too_many_rows exception to propagate up to the caller. Since you don't expect to have multiple rows, that is exactly the behavior that you want. Using aggregate functions hides the fact that the underlying data has problems causing you to return potentially incorrect results and making it impossible to detect that there is a problem. I would always rather get an error as soon as something is causing duplicate rows to appear-- allowing me to fix the problem before it gets out of hand-- rather than finding out years later that we've got millions of duplicate rows, that the code has been occasionally returning incorrect results, and that we have a huge data cleansing effort after addressing the root cause.

like image 108
Justin Cave Avatar answered Jan 04 '23 06:01

Justin Cave


As an alternative to Justin Cave's suggestion, you can rewrite the query slightly so that it always returns a row — something like this:

SELECT NVL(Value1, 0) INTO lValue
FROM   Table1
RIGHT
JOIN   dual
ON     Field1 = lTempValue
like image 40
ruakh Avatar answered Jan 04 '23 05:01

ruakh