您可以检查一列是否存在并使用oracle执行其他操作吗?

时间:2018-12-28 07:28:57

标签: java oracle

我的表格如下所示:

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 +次查询。这可能需要很长时间,并且可能不是最有效的方法。我正在尝试另一种方式。

4 个答案:

答案 0 :(得分:1)

您可以通过两种方法完成此操作

方法1:

  1. 在数据库中创建一个临时表,然后将RAM中的所有值插入该临时表中
  2. 根据您的主表和临时表的连接以及 在临时表中设置一个标记,该标记的值是更新的,该值是不更新 使用插入查询进行插入。

方法2:

  1. 您可以创建自己的数据类型,该数据类型接受值数组作为输入: CREATE OR REPLACE TYPE MyType AS VARRAY(200) OF VARCHAR2(50);
  2. 您可以使用自己的逻辑编写过程,过程将以数组的值作为输入: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

  • 如果键存在,则将计数增加1
  • 如果键不存在,请插入其初始计数为1

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列由序列填充;请根据需要进行修改)。