我有一个包含产品评论的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,我该怎么办呢?
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
你考虑过使用序列吗?它将提供独特性,每个新值都将比前一个更大(但是,不会无间隙,但是 - 在我看来 - 你不应该担心这一点)。
这就是documentation所说的;看看,如果你有兴趣的话。
这是一个演示:我正在创建一个序列和两个表(评论和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
));