在PostgreSQL中同步两个表

在PostgreSQL中同步两个表,postgresql,plpgsql,Postgresql,Plpgsql,我还没有掌握SQL,我想对两个表进行特定的同步: 同步不应实时发生,它将被触发 我有一个文本参数可用于(username)从.txt文件中提取第二个表 这两个表有两个公共列:一个是id,另一个是write\u date作为无时区的时间戳,表示行的最后修改时间。因此,给定一个id,根据写入日期,第一行或第二行应该更新(表不相同,进程也不对称) 我真的不知道是否需要创建函数,因为我可能会从类似“psql db_name

我还没有掌握SQL,我想对两个表进行特定的同步:

  • 同步不应实时发生,它将被触发
  • 我有一个文本参数可用于(
    username
    )从.txt文件中提取第二个表
  • 这两个表有两个公共列:一个是
    id
    ,另一个是
    write\u date
    作为
    无时区的时间戳,表示行的最后修改时间。因此,给定一个id,根据写入日期,第一行或第二行应该更新(表不相同,进程也不对称)
  • 我真的不知道是否需要创建函数,因为我可能会从类似“psql db_name
所以我应该这样做:

CREATE OR REPLACE FUNCTION updatedata(username TEXT) RETURNS void AS $$
DECLARE
    row
    data TEXT
    curtime timestamp without time zone := now();
BEGIN
    COPY table2 FROM '/path/to/data/directory' || username || '.txt' DELIMITER ';' CSV;
    FOR row IN
        SELECT table1.id,table1.data1,table2.data2 
        FROM table1 INNER JOIN table2 ON table1.id=table2.id
        WHERE table1.write_date<table2.write_date
    LOOP
        --Process data
        UPDATE table1 SET data1 = data WHERE id = row.id;
        RETURN NEXT row;
    END LOOP;
    --Second FOR/LOOP
END;
$$ LANGUAGE plpgsql;

updatedata('user1');
CREATE或REPLACE函数updatedata(用户名文本)返回void作为$$
声明
一行
数据文本
不带时区的curtime时间戳:=now();
开始
将表2从“/path/to/data/directory”| | username | |”复制到“.txt”DELIMITER“;”CSV;
划船
选择table1.id、table1.data1、table2.data2
从table1内部连接table1.id=table2.id上的table2

其中,表1.write_date如果我理解正确,您将表2用作临时保留表。在这种情况下,您应该在使用前将其截断。为了更新主表,您不需要执行循环,而是可以使用基于集合的解决方案。您说table1数据列有来自table2的三列,所以我假设您需要连接;在我的示例中,我没有包含分隔符,但它很容易添加。我认为您需要的是以下内容:

CREATE OR REPLACE FUNCTION updatedata(username TEXT) RETURNS void AS $$
DECLARE
    curtime timestamp without time zone := now();
BEGIN
    TRUNCATE TABLE table2;
    COPY table2 FROM '/path/to/data/directory' || username || '.txt' DELIMITER ';' CSV;
    UPDATE table1 t1 
        SET t1.data1 = t2.data1 || t2.data2 || t2.data3, t1.write_date = curtime
        FROM table2 t2 
        WHERE t1.id = t2.id AND t1.username = $1 
        AND t1.write_date < t2.write_date;
END;
$$ LANGUAGE plpgsql;

updatedata('user1'); 
CREATE或REPLACE函数updatedata(用户名文本)返回void作为$$
声明
不带时区的curtime时间戳:=now();
开始
截断表2;
将表2从“/path/to/data/directory”| | username | |”复制到“.txt”DELIMITER“;”CSV;
更新表1 t1
设置t1.data1=t2.data1 | | t2.data2 | | t2.data3,t1.write|u date=curtime
来自表2 t2
其中t1.id=t2.id,t1.username=1美元
t1.写入日期
请注意,这只会更新现有记录。如果表2中存在新记录,则不会添加这些记录


HTH

如果我理解正确,您将表2用作临时保留表。在这种情况下,您应该在使用前将其截断。为了更新主表,您不需要执行循环,而是可以使用基于集合的解决方案。您说table1数据列有来自table2的三列,所以我假设您需要连接;在我的示例中,我没有包含分隔符,但它很容易添加。我认为您需要的是以下内容:

CREATE OR REPLACE FUNCTION updatedata(username TEXT) RETURNS void AS $$
DECLARE
    curtime timestamp without time zone := now();
BEGIN
    TRUNCATE TABLE table2;
    COPY table2 FROM '/path/to/data/directory' || username || '.txt' DELIMITER ';' CSV;
    UPDATE table1 t1 
        SET t1.data1 = t2.data1 || t2.data2 || t2.data3, t1.write_date = curtime
        FROM table2 t2 
        WHERE t1.id = t2.id AND t1.username = $1 
        AND t1.write_date < t2.write_date;
END;
$$ LANGUAGE plpgsql;

updatedata('user1'); 
CREATE或REPLACE函数updatedata(用户名文本)返回void作为$$
声明
不带时区的curtime时间戳:=now();
开始
截断表2;
将表2从“/path/to/data/directory”| | username | |”复制到“.txt”DELIMITER“;”CSV;
更新表1 t1
设置t1.data1=t2.data1 | | t2.data2 | | t2.data3,t1.write|u date=curtime
来自表2 t2
其中t1.id=t2.id,t1.username=1美元
t1.写入日期
请注意,这只会更新现有记录。如果表2中存在新记录,则不会添加这些记录


HTH

如果要“同步”表,为什么不截断第二个表,然后将第一个表中的所有数据复制到其中。由于兼容性,我不能只复制数据:例如,与第一个表不同的字符包含第二个表中3列的数据。第一个表也是所有用户的数据库,尽管将其添加到where筛选器中没有问题,这也是我需要输入参数“username”的原因。如果要“同步”表,为什么不截断第二个表,然后将第一个表中的所有数据复制到其中呢?由于兼容性,我不能只复制数据:例如,与第一个表不同的字符包含第二个表中3列的数据。第一个表也是所有用户的数据库,尽管将其添加到where筛选器中没有问题,这也是我需要输入参数“username”的原因。感谢truncate的建议和基于集合的解决方案!我的荣幸。请将问题标记为已回答。感谢truncate的建议和基于集合的解决方案!我的荣幸。请将问题标记为已回答。