HiveBrain v1.2.0
Get Started
← Back to all entries
snippetsqlMinor

How to generates VALUES literal expression using a query?

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
generatesexpressionqueryliteralusinghowvalues

Problem

During development and testing VALUES literal expressions are useful because they enable you to store data definition in your SQL query.

WITH foobar(foo, bar) AS (
  VALUES
  (1::integer,'a'::text),
  (2,'b'),
  (3,'c'),
  (4,'d')
)
SELECT * FROM foobar;


However this can become tedious when trying implement really wide or big table.
And it's even more frustrating when this could have been generated from an existing table.

So I there a way to output rows in format easily copy/paste-able as a literal VALUES expression?

The closest I could come by is to output row as record
(please note the meta because this SQL actually try to reverse engineer literal VALUES back from a given literal VALUES).

WITH foobar(foo, bar) AS (
  VALUES
  (1::integer,'a'::text),
  (2,'b'),
  (3,'c'),
  (4,'d')
)

SELECT foobar::record FROM foobar;


Here is the psql output:

foobar
--------
 (1,a)
 (2,b)
 (3,c)
 (4,d)
(4 rows)


However this need extra editing to rightfully quote,type and escape content so should i look for a formatting output trick or an SQL trick?

EDIT: The current top answer is already very good but ideally I would like to know if there is generic way to generate a value expression that can adapt to whatever record type you can throw at (even if it is a composite row with a random numbers of columns).

Let say this could be wrapped in as function like:

row_to_values(IN myrowtype record, OUT myrowtype_as_literal_values text)


At this stage one might wonder "Why not use row_to_json() ?" and yes this could be a valid alternative but we are drifting away from the initial use case I had in mind (quickly generate SQL for testing/occasional purpose) although using json should perform well and is now widely available among PostgreSQL releases.

Even better would be an aggregate function that directly output a clean text definition that specify types on first VALUE and add columns name as alias (but at this stage it's almost a feature proposal an

Solution

Are you looking for this:

WITH foobar(foo, bar) AS (
  VALUES
  (1::integer,'a'::text),
  (2,'b'),
  (3,'c'),
  (4,'d')
)
SELECT format('(%s, %L),', foo, bar) FROM foobar;

  format   
-----------
 (1, 'a'),
 (2, 'b'),
 (3, 'c'),
 (4, 'd'),
(4 rows)

Code Snippets

WITH foobar(foo, bar) AS (
  VALUES
  (1::integer,'a'::text),
  (2,'b'),
  (3,'c'),
  (4,'d')
)
SELECT format('(%s, %L),', foo, bar) FROM foobar;

  format   
-----------
 (1, 'a'),
 (2, 'b'),
 (3, 'c'),
 (4, 'd'),
(4 rows)

Context

StackExchange Database Administrators Q#279236, answer score: 5

Revisions (0)

No revisions yet.