0

我在一个文件中有一个 100k id 的列表。我想遍历这些 id:

对于每个id,检查是否id在表中:

  • 如果是,更新其updated_date标志
  • 如果没有,添加一条新记录(id, updated_date)

我研究并找到了MERGE条款。缺点是,MERGE要求 ids 在一个表中。我只允许在必要时创建一个临时表。

谁能指出我正确的方向?它必须是我可以在我的数据库上运行的脚本,而不是在代码中。

merge into MyTable x
using ('111', '222', all my ids) b
  on (x.id = b.id)
when not matched then 
  insert (id, updated_date) values (b.id, sysdate)
when matched then
  update set x.updated_date = sysdate;

编辑:如果这是我唯一的选择,我现在可以使用临时表。

4

2 回答 2

1

如果您可以从 Oracle 服务器访问该文件,那么您可以定义一个外部表,这将允许您使用 SQL 从文件中读取。

该语法基于 SQL*Loader,它可能不是您想做的临时工作,更多的是重复性任务。

或者,您可以使用 SQL*Loader 本身将其加载到表中,甚至可以使用 Microsoft Access 或类似数据库中的 ODBC。

另一种选择是运行 100,000 次插入。您可以通过每 100 个左右的插入并将它们包装在一个匿名块中来使其执行得更好,这样可以节省到数据库的往返行程,而不是:

insert into tmp values(1);
insert into tmp values(12);
insert into tmp values(145);
insert into tmp values(234);
insert into tmp values(245);
insert into tmp values(345);
....
insert into tmp values(112425);

利用 ...

begin
  insert into tmp values(1);
  insert into tmp values(12);
  insert into tmp values(145);
  insert into tmp values(234);
  ...
  insert into tmp values(245);
end;
/
begin
  insert into tmp values(345);
  ...
  insert into tmp values(112425);
end;
/

如果这是一项常规任务,我肯定会选择外部表。

于 2015-08-21T09:38:16.690 回答
1

鉴于您说您不能创建临时表,一种方法可能是将您的 id 列表转换为一组 union all'd 选择,例如:

123,
234,
...
999

变成

select 123 id from dual union all
select 234 id from dual union all
...
select 999 id from dual

然后,您可以在合并语句中使用它:

merge into MyTable x
using (select 123 id from dual union all
       select 234 id from dual union all
       ...
       select 999 id from dual) b
on (x.id = b.id)
when not matched then insert (id, updated_date) values (b.id, sysdate)
when matched then update set x.updated_date = sysdate;

但是,如果您确实有 100k 个 ID,则解析语句可能需要一段时间!您可能希望拆分查询并拥有多个合并语句。

另一个想法 - 是否没有现有的 GTT 可以“借用”来存储数据?

于 2015-08-21T09:21:38.923 回答