Home > Back-end >  Always have SQL query return atleast one record
Always have SQL query return atleast one record

Time:10-05

SELECT column_a,
       CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b
FROM   table_a;

This does not always returns record, my requirement is to always have at least 1 row returned.

Following a solution here I tried couple of workaround such as union but none of it works.

SELECT 2 as column_a,
       CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b
FROM   table_a
UNION
SELECT -1,-1 FROM table_a;

Is there a way I can make this query return a record even when none is found?

CodePudding user response:

Well, query won't return anything if TABLE_A is empty (as there's no WHERE clause). In any other case, it'll return something.

Though, perhaps you meant to union it with a "dummy" select statement that selects from DUAL, not table_a (see line #6). Line #4 is here just to make the first select return no rows.

SQL> WITH table_a (column_a) AS (SELECT 3 FROM DUAL)
  2  SELECT 2 AS column_a, CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b
  3    FROM table_a
  4   WHERE 1 = 2
  5  UNION
  6  SELECT -1, -1 FROM DUAL;         --> DUAL here, not TABLE_A

  COLUMN_A   COLUMN_B
---------- ----------
        -1         -1

SQL>

CodePudding user response:

What is the problem you're trying to solve? Your title says "PL/SQL" which implies that this is happening in a PL/SQL block. In which case the standard answer would be just to catch the no_data_found exception and populate whatever variables you're fetching the data into with some appropriate default values.

BEGIN
    SELECT column_a, 
           CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b 
      INTO local_variable1, local_variable2
      FROM table_a;
EXCEPTION
  WHEN no_data_found
  THEN
    local_variable1 := 1;
    local_variable2 := -1;
END;

Likely, it would make sense to encapsulate this in a stored function.

If you really want to ensure that the query returns 1 row if there is no data in table_a, you could do something like this

SELECT column_a, 
       CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b 
  FROM table_a
UNION ALL
SELECT 1, -1
  FROM dual
 WHERE NOT EXISTS( SELECT 1 FROM table_a );

CodePudding user response:

You can use:

SELECT *
FROM   (
  SELECT column_a,
         CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b
  FROM   table_a
  UNION ALL              -- Use UNION ALL to keep duplicates from table_a.
  SELECT -1,-1 FROM DUAL -- Use the DUAL table which always has exactly 1 row.
)
WHERE  column_b >= 0     -- All the rows from table_a, if any exist.
OR     ROWNUM = 1        -- Or, just the first row.
;

Which, for the empty table:

CREATE TABLE table_a (column_a INT);

Outputs:

COLUMN_A COLUMN_B
-1 -1

And if you insert data:

INSERT INTO table_a (column_a)
SELECT 1 FROM DUAL UNION ALL
SELECT 2 FROM DUAL UNION ALL
SELECT 6 FROM DUAL UNION ALL
SELECT 10 FROM DUAL UNION ALL
SELECT 11 FROM DUAL UNION ALL
SELECT 11 FROM DUAL UNION ALL
SELECT 15 FROM DUAL;

Then the query outputs:

COLUMN_A COLUMN_B
1 1
2 1
6 1
10 1
11 0
11 0
15 0

db<>fiddle here

  • Related