如何使用查询生成 VALUES 文字表达式?

Mar*_*off 3 postgresql psql

在开发和测试期间,VALUES 文字表达式非常有用,因为它们使您能够在 SQL 查询中存储数据定义。

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

然而,当尝试使用非常宽或大的表时,这可能会变得乏味。如果这可以从现有表中生成,那就更令人沮丧了。


所以我有一种方法可以轻松地将行作为文字 VALUES 表达式复制/粘贴吗?

我能得到的最接近的是输出行作为记录
(请注意元数据,因为此 SQL 实际上尝试从给定的文字 VALUES 反向工程文字 VALUES)。

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

SELECT foobar::record FROM foobar;
Run Code Online (Sandbox Code Playgroud)

这是 psql 输出:

 foobar
--------
 (1,a)
 (2,b)
 (3,c)
 (4,d)
(4 rows)
Run Code Online (Sandbox Code Playgroud)

然而,这需要额外的编辑来正确引用、键入和转义内容,所以我应该寻找格式化输出技巧还是 SQL 技巧?


编辑:当前的最佳答案已经非常好,但理想情况下,我想知道是否有通用方法来生成可以适应您可以抛出的任何记录类型的值表达式(即使它是带有随机数的复合行列)。

假设可以将其包装为如下函数:

row_to_values(IN myrowtype record, OUT myrowtype_as_literal_values text)
Run Code Online (Sandbox Code Playgroud)

在这个阶段,人们可能想知道“为什么不使用 row_to_json() ?” 是的,这可能是一个有效的替代方案,但我们正在偏离我想到的初始用例(快速生成用于测试/偶尔目的的 SQL),尽管使用 json 应该表现良好并且现在在 PostgreSQL 版本中广泛可用。

更好的是一个聚合函数,它直接输出一个干净的文本定义,在第一个 VALUE 上指定类型并添加列名作为别名(但在这个阶段,它几乎是一个功能提案,这里不是正确的地方,我没有人问对于这样的事情)。

不幸的是,我想这目前是一个遥不可及的目标,因为据我所知,它需要对有关查询记录类型的动态元数据进行低级别访问。通过查询 pg_catalog.pg_attribute 对现有表显然是可行的,但我不知道如何通过动态查询实现这一点。

因此,如果有人提出了一个我没有想到的好技巧,那将令人印象深刻,否则不太通用的答案显然值得接受。

Lau*_*lbe 5

你在找这个吗:

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)
Run Code Online (Sandbox Code Playgroud)