使用 CREATE TABLE AS SELECT 如何指定 WITH 条件 (CTE)?

Eva*_*oll 10 postgresql syntax cte sql-standard ctas

PostgreSQL 中有一个旧的和不推荐使用的命令,它早于CREATE TABLE AS SELECT(CTAS)称为SELECT ... INTO .... FROM,它支持WITH子句/公共表表达式(CTE)。所以,例如,我可以做到这一点..

WITH w AS (
  SELECT *
  FROM ( VALUES (1) ) AS t(x)
)
SELECT *
INTO foo
FROM w;
Run Code Online (Sandbox Code Playgroud)

但是,我不能这样做..

WITH w AS (
  SELECT *
  FROM ( VALUES (1) ) AS t(x)
)
CREATE TABLE foo AS
SELECT * FROM w;
Run Code Online (Sandbox Code Playgroud)

或者,我得到

ERROR:  syntax error at or near "CREATE"
LINE 5: CREATE TABLE foo AS
Run Code Online (Sandbox Code Playgroud)

我将如何使用标准化的 CTAS 语法来做到这一点。

Eva*_*oll 15

这可能很尴尬,但您必须将WITH子句从顶部移动到查询中。这是生成表的语句中的一部分,而该声明来之后CREATE TABLE,所以你会使用这个语法。

CREATE TABLE foo AS
WITH w AS (
  SELECT *
  FROM ( VALUES (1) ) AS t(x)
)
SELECT * FROM w;
Run Code Online (Sandbox Code Playgroud)

还值得注意的是,它在官方文档中没有明确说明只是在查询中

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name
    [ (column_name [, ...] ) ]
    [ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
    [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
    [ TABLESPACE tablespace_name ]
    AS query
    [ WITH [ NO ] DATA ]
Run Code Online (Sandbox Code Playgroud)

文档提到了关键字的另外两个用例WITH

  1. 设置 storage_options
  2. 设置 NO DATA

你可以看到它们都像这样使用,

CREATE TABLE foo
WITH (fillfactor = 100)
AS
  WITH w AS (
    SELECT *
    FROM ( VALUES (1) ) AS t(x)
  )
  SELECT * FROM w
WITH NO DATA;
Run Code Online (Sandbox Code Playgroud)

现在你有一张空无一人的桌子。

TABLE foo;
 x 
---
(0 rows)
Run Code Online (Sandbox Code Playgroud)