插入不存在的数据的最佳方式

时间:2016-11-02 10:59:33

标签: sql postgresql database-design

我有以下表格

临时用户表

内容来自API

-------------------------------------
| UserId  |   Location |  Department |
-------------------------------------
| 1       |  Loc1      |  Dep1       |
| 2       |  Loc2      |  Dep40      |
| 3       |  Loc100    |  Dep30      |
-------------------------------------

此处的目标是插入这些数据,但它们属于3个不同的表:

用户表

---------------------------------------
| UserId | LocationID |  DepartmentID |
---------------------------------------
| 1      |  1         |  1         |
| 2      |  2         |  2        |
--------------------------------------

---------------------------------
| DepId |       DepName         |
---------------------------------
| 1      |  Dep1         
| 2      |  Dep40     
 ....
| 30 (new)|  Dep40 --> New value
----------------------------------

地点

---------------------------------
| LocId |       LocName         |
---------------------------------
| 1      |  Loc1         
| 2      |  Loc240     
 ....
| 10 (new)|  Loc100 --> New value
----------------------------------

基于这个temp_user表,我应该能够添加一个新用户并插入缺少的部门和位置以具有类似这样的内容 考虑到例如:

  • 30是Dep40的ID
  • 10是Loc100的ID

我的用户表应如下所示

---------------------------------------
| UserId | LocationID |  DepartmentID |
---------------------------------------
| 1      |  1         |  Dep1         |
| 2      |  2         |  Dep40        |
| 3      |  10        |  30           |
--------------------------------------

问题

进行此插入的最佳方法是什么?我可以使用某些触发器来执行此操作,还是应该创建存储过程?什么是正确的算法呢?

1 个答案:

答案 0 :(得分:1)

假设部门名称和位置名称是唯一的,您可以执行以下操作:

-- insert missing locations
insert into location (loc_name)
select location 
from temp_users
on conflict (loc_name) do nothing;

-- insert missing departments
insert into department (dep_name)
select department
from temp_users
on conflict (dep_name) do nothing;

-- insert new users
insert into users (id, location_id, department_id)
select tu.user_id, l.id, d.id
from temp_users tu
  join location l on l.loc_name = tu.location
  join department d on d.dep_name = tu.department
on conflict (id) do nothing; -- ignore existing users with the same ID

以上假设所有id列都定义为主键,locationdepartment的ID是使用序列生成的(例如,将它们定义为{{1}并且seriallocation.loc_name上定义了唯一约束。

实例:http://rextester.com/SND63582