PostgreSQL嵌套INSERTs/WITHs用于外键插入

Cmd*_*ozy 15 sql database postgresql

我正在使用PostgreSQL 9.3,我正在尝试编写一个SQL脚本来为单元测试插入一些数据,而且我遇到了一些问题.

假设我们有三个表,结构如下:

------- Table A -------    -------- Table B --------    -------- Table C --------
id  | serial NOT NULL      id   | serial NOT NULL       id   | serial NOT NULL
foo | character varying    a_id | integer NOT NULL      b_id | integer NOT NULL
                           bar  | character varying     baz  | character varying
Run Code Online (Sandbox Code Playgroud)

B.a_idC.b_id外键的id表列AB分别.

我正在尝试做的是使用纯SQL在这三个表中的每一个表中插入一行,而不将ID硬编码到SQL中(在运行此脚本之前对数据库进行假设似乎是不合需要的,因为如果这些假设改变我将不得不返回并重新计算所有测试数据的正确ID.

请注意,我确实意识到我可以以编程方式执行此操作,但通常编写纯SQL比编写执行SQL的程序代码更简洁,因此对测试套件数据更有意义.

无论如何,这是我写的查询,我认为它可以工作:

WITH X AS (
    WITH Y AS (
        INSERT INTO A (foo)
        VALUES ('abc')
        RETURNING id
    )
    INSERT INTO B (a_id, bar)
    SELECT id, 'def'
    FROM Y
    RETURNING id
)
INSERT INTO C (b_id, baz)
SELECT id, 'ghi'
FROM X;
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,导致PostgreSQL告诉我:

ERROR:  WITH clause containing a data-modifying statement must be at the top level
Run Code Online (Sandbox Code Playgroud)

有没有正确的方法来编写这种类型的查询,而不对ID值进行硬编码?

(你可以在这里找到一个包含这个例子的小提琴.)

a_h*_*ame 27

不要嵌套公用表表达式,只需一个接一个地写:

WITH Y AS (
  INSERT INTO A (foo)
  VALUES ('abc')
  RETURNING id
), x as (
  INSERT INTO B (a_id, bar)
  SELECT id, 'def'
  FROM Y
  RETURNING id
)
INSERT INTO C (b_id, baz)
SELECT id, 'ghi'
FROM X;
Run Code Online (Sandbox Code Playgroud)