tags:

views:

406

answers:

3

I'm looking for the best way to select numbers directly from an in clause.

Basically like:

SELECT * FROM (2,6,1,8);

That doesn't work. I can do it this way:

SELECT Lv FROM (  SELECT Level LV
                  FROM DUAL
                  CONNECT BY Level < 20)
WHERE Lv IN (2,6,1,8);

But that seems to be a bit clunky. Is there a more elegant way?

A: 

If you don't explicitly need the IN clause, you could use UNION:

  select 2 from dual
  union
  select 6 from dual
  union
  select 1 from dual
  union
  select 8 from dual

There is a more elegant variant to INSERT multiple rows into a table:

INSERT ALL
   INTO table (col) VALUES ('a')
   INTO table (col) VALUES ('b')
   INTO table (col) VALUES ('c')
SELECT * FROM dual;

But I don't know a way to do that for a SELECT.

Andomar
A: 

It's more elegant if you materialize an auxiliary numbers table:

SELECT num FROM numbers WHERE num IN (2,6,1,8);

And this is also useful when combined with another table.

For instance, I've had a case where I needed to populate large configuration tables with changes from piecewise results:

Big SP or Excel sheet or report identifies missing cost centers in config gives a large set of results which need to be inserted with varying data in some groups.

Paste partial results into a individual comma separated lists:

INSERT INTO {stuff}
SELECT {stuff}, 130 as line_item
FROM numbers
WHERE numbers.num IN ({pasted a section of results})

INSERT INTO {stuff}
SELECT {stuff}, 135 as line_item
FROM numbers
WHERE numbers.num IN ({pasted another section of results})
Cade Roux
Great idea. I've used RowNum with ALL_OBJECTS before but it just doesn't feel right.
Tom Hubbard
What's the use of the numbers table here? Couldn't one just write "FROM {big construct} WHERE cost_center in ({selection of results})" ?
Andomar
Sorry, that was a bad example. I'll correct it.
Cade Roux
Storing all the numbers in a "numbers" table wastes disk space and has no appreciable benefit over the OP's suggestion of querying SELECT Level FROM DUAL CONNECT BY Level < 20. In fact it will be quite a bit less efficient because Oracle will still read all those blocks from disk for the "numbers" table.
Jeffrey Kemp
Sorry, to be more accurate: Oracle will still read all those blocks (from disk or the cache).
Jeffrey Kemp
@Jeffrey Kemp: Sure, I always have a numbers table and use it for all kinds of things like generating data, generating continuous ranges of values for gap analysis, etc. Appropriately indexed, of course. I mainly work on SQL Server, and this question was closely related to some inserts I recently had to do in several batches.
Cade Roux
+2  A: 

You can do

select column_value from table(sys.dbms_debug_vc2coll(1,2,3,4,5));

but that actually returns a varchar2. You can create your own TYPE and use that

create type tab_num is table of number;
/
select column_value from table(tab_num(1,2,3,4,5));

It's also worth looking at the MODEL clause. It looks complicated, but it is very good at generating data

SELECT x from dual
MODEL DIMENSION BY (1 AS z) MEASURES (1 x)
  RULES ITERATE (7) (x[ITERATION_NUMBER]=ITERATION_NUMBER+1)
Gary