微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在父表中插入单行,然后在PostgreSQL中的单个SQL中插入子表中的多行?

请在我的架构下面找到:

CREATE TABLE reps (
  id    SERIAL PRIMARY KEY,rep   TEXT NOT NULL UNIQUE
);

CREATE TABLE terms (
  id    SERIAL PRIMARY KEY,terms TEXT NOT NULL UNIQUE
);

CREATE TABLE shipVia (
  id        SERIAL PRIMARY KEY,ship_via  TEXT NOT NULL UNIQUE
);

CREATE TABLE invoices (
  id                    SERIAL PRIMARY KEY,customer              TEXT NOT NULL CONSTRAINT customerNotEmpty CHECK(customer <> ''),term_id               INT REFERENCES terms,rep_id                INT NOT NULL REFERENCES reps,ship_via_id           INT REFERENCES shipVia,...
  item_count            INT NOT NULL,modified              TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,created               TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,version               INT NOT NULL DEFAULT 0
);

CREATE TABLE invoiceItems (
  id            SERIAL PRIMARY KEY,invoice_id    INT NOT NULL REFERENCES invoices ON DELETE CASCADE,name          TEXT NOT NULL CONSTRAINT nameNotEmpty CHECK(name <> ''),description   TEXT,qty           INT NOT NULL CONSTRAINT validQty CHECK (qty > 0),price         DOUBLE PRECISION NOT NULL
);

我试图使用可写CTE在一个sql中插入发票及其发票项目.我目前坚持使用以下sql语句:

WITH new_invoice AS (
    INSERT INTO invoices (id,customer,term_id,ship_via_id,rep_id,...,item_count)
    SELECT $1,$2,t.id,s.id,r.id,$26
    FROM reps r
    JOIN terms t ON t.terms = $3
    JOIN shipVia s ON s.ship_via = $4
    WHERE r.rep = $5
    RETURNING id
) INSERT INTO invoiceItems (invoice_id,name,qty,price,description) VALUES
 (new_invoice.id,$27,$28,$29,$30),(new_invoice.id,$31,$32,$33,$34),$35,$36,$37,$38);

当然,这个sql错误的,这就是Postgresql 9.2对它的看法:

ERROR:  missing FROM-clause entry for table "new_invoice"
LINE 13:  (new_invoice.id,$30)
           ^


********** Error **********

ERROR: missing FROM-clause entry for table "new_invoice"
sql state: 42P01
Character: 704

有可能吗?

编辑1

我正在尝试以下版本:

PREPARE insert_invoice_3 AS WITH 
new_invoice AS (
    INSERT INTO invoices (id,item_count) 
    SELECT $1,$26
    FROM reps r
    JOIN terms t ON t.terms = $3
    JOIN shipVia s ON s.ship_via = $4
    WHERE r.rep = $5
    RETURNING id
),v (name,description) AS (
    VALUES ($27,($31,($35,$38)
) 
 INSERT INTO invoiceItems (invoice_id,description)
 SELECT new_invoice.id,v.name,v.qty,v.price,v.description
 FROM v,new_invoice;

这是我得到的回报:

ERROR:  column "qty" is of type integer but expression is of type text
LINE 19:  SELECT new_invoice.id,v.descriptio...
                                         ^
HINT:  You will need to rewrite or cast the expression.

********** Error **********

ERROR: column "qty" is of type integer but expression is of type text
sql state: 42804
Hint: You will need to rewrite or cast the expression.
Character: 899

我猜v(名称,数量,价格,描述)是不够的,还必须指定数据类型.但是,v(名称,数量INT,描述)不起作用 – 语法错误.

编辑2

接下来,我刚刚尝试了第二个版本:

PREPARE insert_invoice_3 AS WITH 
new_invoice AS (
        INSERT INTO invoices (id,item_count) 
        SELECT $1,$26
        FROM reps r
        JOIN terms t ON t.terms = $3
        JOIN shipVia s ON s.ship_via = $4
        WHERE r.rep = $5
        RETURNING id
) 
 INSERT INTO invoiceItems (invoice_id,description)
(
 SELECT i.id,$30 FROM new_invoice i
 UNION ALL
 SELECT i.id,$34 FROM new_invoice i
 UNION ALL
 SELECT i.id,$38 FROM new_invoice i
);

这是我得到的:

ERROR:  column "qty" is of type integer but expression is of type text
LINE 15:  SELECT i.id,$30 FROM new_invoice i
                            ^
HINT:  You will need to rewrite or cast the expression.

********** Error **********

ERROR: column "qty" is of type integer but expression is of type text
sql state: 42804
Hint: You will need to rewrite or cast the expression.
Character: 759

似乎是同样的错误.有趣的是,如果我删除所有UNION ALL并只留下一个SELECT语句 – 它可以工作!

编辑3

为什么我要投射参数?是否可以在CTE中指定列的类型?

解决方法

Postgresql对VALUES子句有如此扩展的解释,它可以单独用作子查询.

因此,您可以用以下形式表达您的查询

WITH new_invoice AS (
    INSERT INTO ...
    RETURNING id
),v(a,b,c,d) AS (values
  ($27,...
)
INSERT INTO invoiceItems (invoice_id,a,d FROM v,new_invoice;

这假设您想要插入new_invoice的笛卡尔积和值,如果new_invoice实际上是单行值,这通常是有意义的.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐