create table permanent ( key int primary key, field1 int, field2 text );
create temporary table temporary as select * from permanent where false;
\copy temporary from 'actual_data.dump'
alter table temporary add constraint temporary_pkey primary key ( key );
update permanent
set field1 = temporary.field1,
field2 = temporary.field2
from temporary
where permanent.key = temporary.key
and ( permanent.field1 is distinct from temporary.field1
or permanent.field2 is distinct from temporary.field2
);
delete from permanent where not exists ( select 1
from temporary
where key = permanent.key );
insert into permanent ( select *
from temporary
where not exists ( select 1
from permanent
where key = temporary.key ) );
这至少适用于 postgresql。
对于甲骨文,我使用以下内容:
update ( select p.field1 p_field1,
p.field2 p_field2,
t.field1 t_field1,
t.field2 t_field2
from permanent p, temporary t
where p.key = t.key )
set p_field1 = t_field1,
p_field2 = t_field2
where p_field1 <> t_field1
or p_field1 is null and t_field1 is not null
or p_field1 is not null and t_field1 is null
or p_field2 <> t_field2
or p_field2 is null and t_field2 is not null
or p_field2 is not null and t_field2 is null
当我有不可能的值时,我可以改用 NVL:
where nvl(p_field1, -1) <> nvl(t_field1, -1)
or nvl(p_field2, '{null}') <> nvl(t_field2, '{null}')
您需要删除并重新加载数据库吗?在像您这样的情况下,我会寻找一种方法将数据库与参考集(您正在加载的数据)同步。
另一种方法是拥有两个数据库。每天加载一个不同的。配置 webapp,以便您可以即时交换数据库。
好吧,这在大多数数据库中都很简单。当您的应用程序正在运行时,从您的加载作业中:
DELETE
表中的所有数据(不删除或截断)INSERT
新数据COMMIT
交易当步骤 1-3 运行时,应用程序将看到“旧”版本的数据并可以正常继续。即时第 4 步完成后,应用程序将在运行下一个查询时立即看到新数据。
截断表,然后批量加载数据。如果需要,在截断表之前从表中锁定 Web 应用程序。
这取决于依赖树的情况。如果在加载数据的表 [s] 上有很多依赖对象,最好不要更改对象和表,因为会发生很多失效。
truncate table 可以非常快速地删除数据,但在存在引用约束时将不起作用。由于锁定问题,它在应用程序运行时也不会工作。
最适合应用程序的是正常的删除/插入序列。不是最快的选择,但它是可用性最好的,并且锁定问题最少。
其他选项可以分区交换加载。约束可能会产生问题,并且需要花费大量时间来验证。永远不要为了删除数据而删除表。表被视为应用程序基础设施并且应该始终可用,因为应用程序会向您的用户抛出很多错误。
我将新数据加载到临时表中。这样,我只需要锁定需要更新的行。之后我删除丢失的行并插入新行。
这至少适用于 postgresql。
对于甲骨文,我使用以下内容:
当我有不可能的值时,我可以改用 NVL: