简体   繁体   English

如何同时插入两个表

[英]How to insert into two tables at the same time

I hope I am able to explain this properly. 我希望我能正确解释。 I need to insert data into two DB tables. 我需要将数据插入两个数据库表中。 This data is already stored in two other tables but needs to be migrated. 此数据已存储在其他两个表中,但需要迁移。 To simplify things lets say here are my source tables: 为了简化起见,可以说这是我的源表:

folder with columns folderid, foldername 具有列folderid,foldername的文件夹

link with columns linkid, url and folderid 与列linkid,url和folderid链接

And my destination tables are: 我的目标表是:

new_folder with columns folderid, foldername new_folder,具有列folderid,foldername

new_link with columns linkid, url and folderid new_link带有列linkid,url和folderid的列

There are other columns also but they are not important. 也有其他专栏,但它们并不重要。 My problem is that whoever setup the original database used a random number generator in java to create the folder and link ids and these numbers are complete garbage. 我的问题是,设置原始数据库的任何人都使用Java中的随机数生成器来创建文件夹和链接ID,而这些数字是完全垃圾。 They need to be replaced with a number generated by a sequence which exists in the DB. 需要用数据库中存在的序列生成的数字替换它们。

So what I need is one statement that does something like the following: 因此,我需要一个执行如下操作的语句:

insert into new_folder(folderid, foldername), new_link(linkid, url, folderid)
values (select seq_folder_id.nextval, foldername, seq_link_id.nextval, url, seq_folder_id.currval from folder, link where folder.folderid = link.folderid).

There could be multiple links associated with the folder. 文件夹可能有多个链接。 There are 200k rows in the folder table and 10 times that in the link table so I need some sort of a script that will run and pull out all folders and create new entries with the new sequence as the ID. 文件夹表中有20万行,链接表中有10倍,因此我需要某种脚本来运行并拉出所有文件夹,并以新序列作为ID创建新条目。 That on its own would be fine but if I just do that then I have no way of mapping the links to the folders once the ID is changed unless I do it in the one statement if that makes sense. 单独这样做会很好,但是如果我这样做,那么一旦ID更改,我就无法将链接映射到文件夹,除非我在一个声明中这样做就行了。

Here is a good tutorial on multi-table inserts: 这是有关多表插入的很好的教程:

http://www.oracle-developer.net/display.php?id=209 http://www.oracle-developer.net/display.php?id=209

The basic structure is: 基本结构是:

INSERT ALL|FIRST
   [WHEN condition THEN] INTO target [VALUES]
   [WHEN condition THEN] INTO target [VALUES]
   ...
   [ELSE] INTO target [VALUES]
SELECT ...
FROM   source_query;

You will probably want to restructure your source subquery to create a column that indicates the first row for each foldername that you can then use in the when conditions to only insert one row per folder to the folder table, and then all rows to the link table. 您可能需要重组源子查询以创建一列,该列指示每个文件夹名称的第一行,然后可以在when条件下将每个文件夹的每一行仅插入到文件夹表中,然后将所有行插入到链接表中。 You will also have to re-jig how you are generating the IDs so that you have the same folderID for each link row. 您还必须重新设置如何生成ID,以便每个链接行都具有相同的folderID。 In other words, time you learned aggregate functions! 换句话说,您学习集合函数的时间!

Example: look at this query and see if it would help you figure it out (hint, folder_rank can become the basis for the folder_id, and how group_rank could drive a when clause to figure out the folder insert) 示例:查看此查询,看看它是否可以帮助您解决(提示,folder_rank可以成为folder_id的基础,以及group_rank如何驱动when子句来确定文件夹插入)

select dense_rank() over (order by foldername) as folder_rank,
       rank() over (parition by foldername order  by url) as group_rank
     , foldername
     , seq_link_id.nextval
     , url 
from folder, link 
where folder.folderid = link.folderid

Alternately, look at doing this in a chunk of pl/sql rather than pure SQL: 或者,看一下在pl / sql而不是纯SQL中执行此操作:

declare
  l_new_folder_id new_folder.folder_id%type;
begin
   for folder_Rec in (select folder_id, foldername from folder)
   loop
      insert into new_folder (folder_id, folder_name) 
      values ( seq_folder_id.nextval, folder_Rec.folder_name) 
      returning folder_id into l_new_folder_id;

      for link_rec in (select url from link where folder_id = folder_rec.folder_id)
          insert into new_link (link_id, folder_id, url) 
          values (seq_link_id.nextval, l_new_folder_id, link_rec.url);
      end loop;
    end loop;
    commit;
end;

There are several ways to skin this cat, and complex SQL may not be the best option for a beginner. 有几种方法可以使这只猫变皮,对于初学者来说,复杂的SQL可能不是最佳选择。 Also, check your source data - if you have folders that do not have any links then the pure SQL approach will also have to incoporate an outer join rather than the current definition if you want the link-less folders to be inserted. 另外,检查您的源数据-如果您的文件夹没有任何链接,那么如果要插入无链接文件夹,则纯SQL方法也必须合并外部联接,而不是当前定义。 The PL/Sql solution will already handle that scenario. PL / Sql解决方案已经可以解决这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM