238

Selecting constants without referring to a table is perfectly legal in an SQL statement:

SELECT 1, 2, 3

The result set that the latter returns is a single row containing the values. I was wondering if there is a way to select multiple rows at once using a constant expression, something kind of:

SELECT ((1, 2, 3), (4, 5, 6), (7, 8, 9))

I would want something like the above that works and returns a result set with 3 rows and 3 columns.

Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
  • 1
    Your imagined syntax above is prettier (and more consistent with INSERT INTO) than the official syntax. Just say'in. – Pete Alvin Oct 08 '14 at 21:56
  • 2
    @PeteAlvin The imagined syntax already has a meaning in Postgres (a single row with a tuple is selected). – Kirill Bulygin Oct 17 '18 at 13:19
  • 2
    The sql server answer below works well for sql server, and almost matches this syntax. https://stackoverflow.com/a/53269562/2129481 – BenPen Dec 12 '18 at 15:57

17 Answers17

256
SELECT 1, 2, 3
UNION ALL SELECT 4, 5, 6
UNION ALL SELECT 7, 8, 9
Dewfy
  • 23,277
  • 13
  • 73
  • 121
  • 4
    I used this with SQL Server and it worked, but I had to use `AS` to give aliases on the first `SELECT` – Sled May 18 '17 at 18:34
  • thank you @ArtB, this comment may help other developers to get correct syntax – Dewfy May 18 '17 at 19:12
  • 5
    Also works perfectly in Oracle APEX 5.1 to create `Classic Report` tables with static content, if completed with `FROM dual` after each `SELECT`, values and before `UNION ALL` if present. – VELFR Jul 02 '18 at 11:55
156

In PostgreSQL, you can do:

SELECT  *
FROM    (
        VALUES
        (1, 2),
        (3, 4)
        ) AS q (col1, col2)

In other systems, just use UNION ALL:

SELECT  1 AS col1, 2 AS col2
-- FROM    dual
-- uncomment the line above if in Oracle
UNION ALL
SELECT  3 AS col1, 3 AS col2
-- FROM    dual
-- uncomment the line above if in Oracle

In Oracle, SQL Server and PostgreSQL, you also can generate recordsets of arbitrary number of rows (providable with an external variable):

SELECT  level
FROM    dual
CONNECT BY
        level <= :n

in Oracle,

WITH    q (l) AS
        (
        SELECT  1
        UNION ALL
        SELECT  l + 1
        FROM    q
        WHERE   l < @n
        )
SELECT  l
FROM    q
-- OPTION (MAXRECURSION 0)
-- uncomment line above if @n >= 100

in SQL Server,

SELECT  l
FROM    generate_series(1, $n) l

in PostgreSQL.

Quassnoi
  • 413,100
  • 91
  • 616
  • 614
25

For Microsoft SQL Server or PostgreSQL you may want to try this syntax

SELECT constants FROM (VALUES ('foo@gmail.com'), ('bar@gmail.com'), ('baz@gmail.com')) AS MyTable(constants)

You can also view an SQL Fiddle here: http://www.sqlfiddle.com/#!17/9eecb/34703/0

bigtunacan
  • 4,873
  • 8
  • 40
  • 73
  • 3
    This absolutely works in SQL server 2010. Multiple columns too: SELECT constants,email FROM (VALUES (1,'foo@gmail.com'), (2,'bar@gmail.com'), (3, 'baz@gmail.com')) AS MyTable(constants,email) – BenPen Dec 12 '18 at 15:36
  • How do you name the columns? I've got for example `'foo@gmail.com' AS email` but I get the error `Incorrect syntax near the keyword 'AS'` – Michael Oct 27 '22 at 21:57
  • @Michael would help if you had the full query – bigtunacan Nov 02 '22 at 14:40
21

The following bare VALUES command works for me in PostgreSQL:

VALUES (1,2,3), (4,5,6), (7,8,9)
Tregoreg
  • 18,872
  • 15
  • 48
  • 69
  • 1
    Works in T-SQL as a multi-row insert clause, too. Inserting into a table variable or temporary table first could work, but multiple steps. – brianary Feb 17 '16 at 20:51
15

Oracle. Thanks to this post PL/SQL - Use "List" Variable in Where In Clause

I put together my example statement to easily manually input values (being reused in testing an application by testers):

WITH prods AS (
    SELECT column_value AS prods_code 
    FROM TABLE(
        sys.odcivarchar2list(
            'prod1', 
            'prod2'
        )
    )
)
SELECT * FROM prods
Petr Szturc
  • 804
  • 6
  • 9
  • 1
    This was a life saver. One thing to note: If you have run into a too many values error, you can just do a UNION ALL in the WITH clause. – ScrappyDev Sep 18 '18 at 19:47
13

Try the connect by clause in oracle, something like this

select level,level+1,level+2 from dual connect by level <=3;

For more information on connect by clause follow this link : removed URL because oraclebin site is now malicious.

Michał Stochmal
  • 5,895
  • 4
  • 36
  • 44
Sushant Butta
  • 520
  • 5
  • 8
6
SELECT * 
FROM DUAL 
CONNECT BY ROWNUM <= 9;
bluish
  • 26,356
  • 27
  • 122
  • 180
grokster
  • 5,919
  • 1
  • 36
  • 22
5

Here a way to create custom rows directly with MySQL request SELECT :

SELECT ALL *
FROM (
    VALUES
        ROW (1, 2, 3),
        ROW (4, 5, 6),
        ROW (7, 8, 9)
) AS dummy (c1, c2, c3)

Gives us a table dummy :

c1   c2   c3
-------------
 1    2    3
 4    5    6
 7    8    9

Tested with MySQL 8

JCH77
  • 1,125
  • 13
  • 13
4

Here is how I populate static data in Oracle 10+ using a neat XML trick.

create table prop
(ID NUMBER,
 NAME varchar2(10),
 VAL varchar2(10),
 CREATED timestamp,
 CONSTRAINT PK_PROP PRIMARY KEY(ID)
);

merge into Prop p
using (
select 
  extractValue(value(r), '/R/ID') ID,
  extractValue(value(r), '/R/NAME') NAME,
  extractValue(value(r), '/R/VAL') VAL
from
(select xmltype('
<ROWSET>
   <R><ID>1</ID><NAME>key1</NAME><VAL>value1</VAL></R>
   <R><ID>2</ID><NAME>key2</NAME><VAL>value2</VAL></R>
   <R><ID>3</ID><NAME>key3</NAME><VAL>value3</VAL></R>
</ROWSET>
') xml from dual) input,
 table(xmlsequence(input.xml.extract('/ROWSET/R'))) r
) p_new
on (p.ID = p_new.ID)
when not matched then
insert
(ID, NAME, VAL, CREATED)
values
( p_new.ID, p_new.NAME, p_new.VAL, SYSTIMESTAMP );

The merge only inserts the rows that are missing in the original table, which is convenient if you want to rerun your insert script.

Nicholas Sushkin
  • 13,050
  • 3
  • 30
  • 20
3

An option for DB2:

SELECT 101 AS C1, 102 AS C2 FROM SYSIBM.SYSDUMMY1 UNION ALL
SELECT 201 AS C1, 202 AS C2 FROM SYSIBM.SYSDUMMY1 UNION ALL
SELECT 301 AS C1, 302 AS C2 FROM SYSIBM.SYSDUMMY1
Vitaliy Ulantikov
  • 10,157
  • 3
  • 61
  • 54
2

In MySQL, you can do: values (1,2), (3, 4);

mysql> values (1,2), (3, 4);
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
| 3 | 4 |
+---+---+
2 rows in set (0.004 sec)

With MySQL 8, it is also possible to give the column names:

mysql> SELECT * FROM (SELECT 1, 2, 3, 4) AS dt (a, b, c, d);
+---+---+---+---+
| a | b | c | d |
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
Benedikt Köppel
  • 4,853
  • 4
  • 32
  • 42
  • 1
    what version of mysql are you on for "values (1,2), (3, 4);"? – Rene Wooller Jun 04 '19 at 05:08
  • Is that second example actually still selecting multiple rows? Also neither of them seem to be runnable as queries in PhpMyAdmin.. I wish I could tell you which version of MySQL I am on, but MySQL versions are so confusing, and I'm sure by the time I figure it out, I will be out of time to edit this comment... – still_dreaming_1 Apr 28 '20 at 15:35
  • @ReneWooller don't know about op, but `VALUES` works for me on MariaDB 10.5.12 – Matija Nalis Nov 05 '21 at 18:17
2

In Oracle SQL you can use JSON_TABLE to create table from JSON:

SELECT
   t.emp_name,
   t.emp_age
FROM
   JSON_TABLE (
   '{
     "employees": [{name:"Alice", age: 19}, {name: "Bob", age: 23}]
  }',
  '$'
  COLUMNS (
     NESTED PATH '$.employees[*]'
     COLUMNS (
        emp_name VARCHAR2(50) PATH '$.name',
        emp_age NUMBER(3,0) PATH '$.age'
     )
  )
) t;
Michał Stochmal
  • 5,895
  • 4
  • 36
  • 44
1

In Oracle

SELECT
  CASE
    WHEN level = 1
    THEN 'HI'
    WHEN level = 2
    THEN 'BYE'
  END TEST
FROM dual
  CONNECT BY level <= 2;
bobs
  • 21,844
  • 12
  • 67
  • 78
  • `SELECT CASE WHEN level = 1 THEN 'HI' WHEN level = 2 THEN 'BYE' END field_desc, level as seq_code FROM dual CONNECT BY level <= 3;` better what you mean when you do it like this. but thanks this was what I was looking for – and-bri Dec 01 '21 at 10:12
1

With SQLite3, the following select Go .QueryContext()

VALUES (1), (2)

Returns a single untyped column named “Column1” and two rows with values 1 and 2

VALUES is a special form of the simple SELECT statement https://www.sqlite.org/lang_select.html#simpleselect

Harald Rudell
  • 787
  • 6
  • 7
0

Here is how to do it using the XML features of DB2

SELECT *
FROM
XMLTABLE ('$doc/ROWSET/ROW' PASSING XMLPARSE ( DOCUMENT '
<ROWSET>
  <ROW>
    <A val="1" /> <B val="2" /> <C val="3" />
  </ROW>
  <ROW>
    <A val="4" /> <B val="5" /> <C val="6" />
  </ROW>
  <ROW>
    <A val="7" /> <B val="8" /> <C val="9" />
  </ROW>
</ROWSET>
') AS "doc"
   COLUMNS 
      "A" INT PATH 'A/@val',
      "B" INT PATH 'B/@val',
      "C" INT PATH 'C/@val'
) 
AS X
;
Stavr00
  • 3,219
  • 1
  • 16
  • 28
0

This way can help you

SELECT   TOP 3
         1 AS First, 
         2 AS Second, 
         3 AS Third 
FROM     Any_Table_In_Your_DataBase

Any_Table_In_Your_DataBase: any table which contains more than 3 records, or use any system table. Here we have no concern with data of that table.

You can bring variations in result set by concatenating a column with First, Second and Third columns from Any_Table_In_Your_DataBase table.

Lali
  • 2,816
  • 4
  • 30
  • 47
0
select (level - 1) * row_dif + 1 as a, (level - 1) * row_dif + 2 as b, (level - 1) * row_dif + 3 as c
    from dual 
    connect by level <= number_of_rows;

something like that

select (level - 1) * 3 + 1 as a, (level - 1) * 3 + 2 as b, (level - 1) * 3 + 3 as c
    from dual 
    connect by level <= 3;
Dejoto
  • 1