插入多个记录,其中一个字段取决于表中的现有值

时间:2018-03-05 15:34:38

标签: sql oracle

我有一个包含产品评论的Oracle数据库表。其中一列是sort_order - 即从数据库读入Web前端时显示评论的顺序。

我需要从临时加载表(已经从CSV填充)批量插入一堆新评论到主评论表中。我的SQL是这样的:

INSERT INTO reviews
(product_code, sort_order, review_date, review_text)
(SELECT product_code, 10, review_date, review_text
   FROM review_load_table)
;

但是,当然这不正确 - 只需在10列中插入sort_order即可获得每次新评价。
那么,如果我希望插入sort_order字段的值比相应产品的最大现有值大1,我该怎么办呢?

2 个答案:

答案 0 :(得分:2)

INSERT INTO reviews (product_code, sort_order, review_date, review_text)
    SELECT rlt.product_code, COALESCE(1 + rp.maxso, 1),
           rlt.review_date, rlt.review_text
    FROM review_load_table rlt LEFT JOIN
         (SELECT r.product_code, MAX(sort_order) as maxso
          FROM reviews r
          GROUP BY r.product_code
         ) rp
         ON rlt.product_code = r.product_code;

如果您可以在临时表中多次出现产品并且想要不同的数字,请使用row_number()

INSERT INTO reviews (product_code, sort_order, review_date, review_text)
    SELECT rlt.product_code,
           COALESCE(rp.maxso, 0) + row_number() over (partition by rlt.product_code order by product_code),
           rlt.review_date, rlt.review_text
    FROM review_load_table rlt LEFT JOIN
         (SELECT r.product_code, MAX(sort_order) as maxso
          FROM reviews r
          GROUP BY r.product_code
         ) rp
         ON rlt.product_code = r.product_code

答案 1 :(得分:0)

您考虑使用序列吗?它将提供独特性,每一个新的价值都会比前一个更大(但是,它不会无间隙,但是 - 在我看来 - 你不应该担心这个)。

这是documentation所说的;看看,如果你有兴趣的话。

以下是演示:我创建了一个序列和两个表(review和review_load_table):

SQL> create sequence seq_sort;

Sequence created.

SQL> create table reviews
  2    (product_code  number,
  3     sort_order    number,
  4     review_text   varchar2(20));

Table created.

SQL> insert into reviews
  2    select 100, seq_sort.nextval, 'Text 1' from dual;

1 row created.

SQL> create table review_load_table
  2    (product_code  number,
  3     review_text   varchar2(20));

Table created.

SQL> -- this insert simulates data loaded from the CSV file
SQL> insert into review_load_table
  2    select 100, 'Text 2' from dual union
  3    select 200, 'Text 3' from dual;

2 rows created.

SQL>

现在,让我们从临时表中复制数据:

SQL> insert into reviews
  2    (product_code, sort_order, review_text)
  3    (select product_code, seq_sort.nextval, review_text
  4     from review_load_table
  5    );

2 rows created.

SQL> select * from reviews order by product_code, sort_order;

PRODUCT_CODE SORT_ORDER REVIEW_TEXT
------------ ---------- --------------------
         100          1 Text 1
         100          2 Text 2
         200          3 Text 3

SQL>

如您所见,SORT_ORDER值已正确设置。

如果您需要在插入期间对行进行预排序(例如,通过时间戳或其他任何列),您可以使用首先排序的子查询,然后将SEQ_SORT.NEXTVAL应用于它:

insert into reviews
  (product_code, sort_order, review_text)
  (select product_code, seq_sort.nextval, review_text
   from (select product_code, review_text
         from review_load_table
         order by review_text desc
        ));