我的表格如下所示:
id | value1 | count
我在RAM中有一个value1
的列表,我想执行以下操作:
(if value1 exists in table){
count + 1}else{
insert new row into table}
使用Oracle可能吗?还是必须将其带入代码,执行for loop
并一次执行列表的一个元素?该列表包含500万个值。我必须在代码中执行以下操作:
for(int i=0; i<list.size; i++){
boolean exists = checkifexists(list.get(i));
if(exists=true){
countPlusOne(list.get(i);
}else{
createNewRow(list.get(i));
}
}
因此,我必须对每个值至少执行两次查询,总计10m +次查询。这可能需要很长时间,并且可能不是最有效的方法。我正在尝试另一种方式。
答案 0 :(得分:1)
您可以通过两种方法完成此操作
方法1:
方法2:
CREATE OR REPLACE TYPE MyType AS VARRAY(200) OF VARCHAR2(50);
CREATE OR REPLACE PROCEDURE testing (t_in MyType)
答案 1 :(得分:1)
在Oracle中,我们可以使用MERGE
语句检查行是否存在,并仅在不存在时进行插入。
首先创建一个定义列表的类型。
CREATE OR REPLACE TYPE value1_type as TABLE OF VARCHAR2(10); --use the datatype of value1
合并语句。
MERGE INTO yourtable t
USING (
select distinct column_value as value1 FROM TABLE(value1_type(v1,v2,v3))
)s ON ( s.value1 = t.value1 )
WHEN NOT MATCHED THEN INSERT
(col1,col2,col3) VALUES ( s.col1,s.col2,s.col3);
您也可以使用NOT EXISTS
。
INSERT INTO yourtable t
select * FROM
(
select distinct column_value as value1 from TABLE(value1_type(v1,v2,v3))
) s
WHERE NOT EXISTS
(
select 1 from
yourtable t where t.value1 = s.value1
);
答案 2 :(得分:1)
首先在临时表TMP
中填充RAM列表
select * from tmp;
VALUE1
----------
V00000001
V00000002
V00000003
V00000004
V00000005
...
您可以使用MERGE
语句来处理您的logik
。
merge into val
using tmp
on (val.value1 = tmp.value1)
when matched then update
set val.count = val.count + 1
when not matched then
insert (val.value1, val.count)
values (tmp.value1, 1)
;
请注意,我假设您在ID
列中拥有IDENTITY
键,因此不需要重新分配键。
如果TMP
表中有重复的记录(更多记录使用相同的VALUE1
键),则会出现错误,因为MERGE
无法使用一个键处理更多操作。
ORA-30926: unable to get a stable set of rows in the source tables
如果您想将每个重复的密钥算作一个-
您必须使用GROUP BY
预汇总临时表并添加counts
。
否则,简单地使用DISTINCT
忽略重复项。
merge /*+ PARALLEL(5) */ into val
using (select value1, count(*) count from tmp group by value1) tmp
on (val.value1 = tmp.value1)
when matched then update
set val.count = val.count + 1
when not matched then
insert (val.value1, val.count)
values (tmp.value1, 1)
答案 3 :(得分:1)
“我将它们从数据库加载到RAM中”
您已经在数据库中拥有源数据,因此您应该在数据库中进行处理。实例化本地内存中的500万个字符串列表并不是一项便宜的操作,尤其是在不必要时。
Oracle支持MERGE功能,我们可以使用该功能来测试目标表中是否存在记录并有条件地填充新行。作为设置操作,MERGE比Java循环中的单行插入更具性能。
棘手的是独特性。您需要从包含唯一值的源表中进行驾驶查询(否则MERGE会弹出)。在此示例中,我汇总了源表中每次value1
出现的次数。这给了我们一组value1
以及一个可用于维护目标表上的count列的数字。
merge into you_target_table tt
using ( select value1
, count(*) as dup_cnt
from your_source_table
group by value1
) st
on ( st.value1 = tt.value1 )
when not matched then
insert (id, value1, cnt)
values (someseq.nextval, st.value1, st.dup_cnt)
when matched then
update
set tt.cnt = tt.cnt + st.dup_cnt;
(我假设目标表的ID列由序列填充;请根据需要进行修改)。