行构造函数有什么用?

What is a row constructor used for?

在 PostgreSQL 中,ROW() 函数有什么用?

具体有什么区别

SELECT ROW(t.f1, t.f2, 42) FROM t;

其中 f1int 类型,f2text

类型

CREATE TYPE myrowtype AS (f1 int, f2 text, f3 numeric);

行构造函数可用于构建复合值以存储在复合类型 table 列中,或传递给接受复合参数的函数。 此外,还可以比较两个行值或用 IS NULL 或 IS NOT NULL 测试一行。

4.2.13. Row Constructors

示例:

CREATE TYPE myrowtype AS (f1 int, f2 text, f3 numeric);
CREATE TABLE mytable (ct myrowtype);
INSERT INTO mytable(ct) VALUES (CAST(ROW(11,'this is a test',2.5) AS myrowtype));

您问的是 valuetype 之间的区别。

这与对象和 OO 语言中的 class 之间的区别大致相同。

在第一种情况下,您正在构建一个可用于比较、行写入或传递给接受复合参数的函数的值。

在第二种情况下,您定义的类型可以在函数或 table 定义中使用。

ROW(...) 不是函数。它是 SQL 语法,更像是 ARRAY[...] 构造函数而不是函数。

ROW 构造函数主要用于形成匿名记录。当您需要将字段集合放在一起,但它们不对应于现有的 table 类型或复合数据类型时,这会很有用。

这两个在Postgre中是等价的SQL:

test=> SELECT t FROM (SELECT 1, 'x', NUMERIC '42.1') AS t;
     t      
------------
 (1,x,42.1)
(1 row)

test=> SELECT ROW(1, 'x', NUMERIC '42.1');
    row     
------------
 (1,x,42.1)
(1 row)

两者都创建匿名记录:

test=> SELECT pg_typeof(t) FROM (SELECT 1, 'x', NUMERIC '42.1') AS t;
 pg_typeof 
-----------
 record
(1 row)

test=> SELECT pg_typeof(ROW(1, 'x', NUMERIC '42.1'));
 pg_typeof 
-----------
 record
(1 row)

ROW 创建的记录可以对应于现有类型,当您将复合类型传递给函数时,例如给定:

CREATE TYPE myrowtype AS (f1 int, f2 text, f3 numeric);

您可以创建一个 myrowtype

test=> SELECT CAST(ROW(1, 'x', '42.1') AS myrowtype);
    row     
------------
 (1,x,42.1)
(1 row)

你混淆了抽象层次。正如其他答案已经指出的那样, CREATE TYPE 仅在系统中注册了一个(复合/行)类型。虽然 ROW 构造函数实际上 returns 一行。

使用 ROW 构造函数创建的行类型不保留列名,这在您尝试将行转换为 JSON.

时变得明显

大多数时候,ROW只是一个噪音词The manual:

The key word ROW is optional when there is more than one expression in the list.

演示:

SELECT t                              AS r1, row_to_json(t)                           AS j1
     , ROW(1, 'x', numeric '42.1')    AS r2, row_to_json(ROW(1, 'x', numeric '42.1')) AS j2
     ,    (1, 'x', numeric '42.1')    AS r3, row_to_json(   (1, 'x', numeric '42.1')) AS j3
     ,    (1, 'x', '42.1')::myrowtype AS r4, row_to_json((1, 'x', '42.1')::myrowtype) AS j4
FROM  (SELECT 1, 'x', numeric '42.1') t;

db<>fiddle here
sqlfiddle

r1j1 保留原始列名称。
r2j2 没有。
r3j3 是一样的;来证明 ROW 只是噪音。
r4j4 带有注册类型的列名。

如果元素的数字数据类型与行类型匹配,您可以将行(记录)转换为已注册的行类型- 输入字段的名称 被忽略。

  • Return multiple columns of the same row as JSON array of objects