ech*_*n00 3 csv postgresql postgresql-9.2
我目前保留了一个 CSV 主文件,我经常更新该文件来管理产品列表。
如果我尝试直接导入 CSV 文件,则会收到错误“重复键值违反唯一约束...”目前,我通过删除表中的所有项目来更新我的 Products Postgres 表,然后再次导入所有数据。
我意识到这不是一个好方法。有更好的方法来解决这个问题吗?我目前使用 pgAdmin III 和 PG Commander 客户端。
您可以通过定义一个触发器函数来完成此操作,该函数尝试更新现有记录,并且仅在未找到记录时才允许继续插入。
当然,要实现此目的,您需要有一个主键或其他标准来唯一标识行。
假设您的表定义如下:
CREATE TABLE TEST(
id INT PRIMARY KEY,
name TEXT,
amount INT
);
Run Code Online (Sandbox Code Playgroud)
触发函数可能如下所示:
CREATE OR REPLACE FUNCTION test_insert_before_func()
RETURNS TRIGGER
AS $BODY$
DECLARE
exists INTEGER;
BEGIN
UPDATE test SET name=new.name, amount=new.amount
WHERE id=new.id
RETURNING id INTO exists;
-- If the above was successful, it would return non-null
-- in that case we return NULL so that the triggered INSERT
-- does not proceed
IF exists is not null THEN
RETURN NULL;
END IF;
-- Otherwise, return the new record so that triggered INSERT
-- goes ahead
RETURN new;
END;
$BODY$
LANGUAGE 'plpgsql' SECURITY DEFINER;
CREATE TRIGGER test_insert_before_trigger
BEFORE INSERT
ON test
FOR EACH ROW
EXECUTE PROCEDURE test_insert_before_func();
Run Code Online (Sandbox Code Playgroud)
现在,如果我插入尚不存在的行,则会插入该行:
test=> insert into test(id,name,amount) values (1,'Mary',100);
INSERT 0 1
test=> select * from test;
id | name | amount
----+------+--------
1 | Mary | 100
(1 row)
Run Code Online (Sandbox Code Playgroud)
如果我尝试插入具有相同 ID 的行:
test=> insert into test(id,name,amount) values (1,'Mary',200);
INSERT 0 0
test=> select * from test;
id | name | amount
----+------+--------
1 | Mary | 200
(1 row)
Run Code Online (Sandbox Code Playgroud)
这次该行被更新而不是插入。
如果我从 CSV 文件加载行,它的效果也一样。
但是:您可能没有考虑到一件事:这不会删除数据库中存在且 CSV 文件中不存在的任何记录。如果你想让它起作用,你将需要一个更复杂的解决方案 - 也许是这样的序列:
从实际表中删除临时表中不存在的所有行。桌子
DELETE FROM test WHERE id NOT IN (SELECT id FROM temp);
Run Code Online (Sandbox Code Playgroud)然后最后从临时插入行。表到真实表:
INSERT INTO test(id,name,amount) (SELECT id,name,amount FROM temp);
Run Code Online (Sandbox Code Playgroud)此答案不考虑并发问题,以防其他用户同时更新表。但是,如果您仅从 CSV 文件加载,那么这不太可能是问题。
| 归档时间: |
|
| 查看次数: |
7762 次 |
| 最近记录: |