postgresql - 具有外键约束的关系数据库如何摄取顺序可能错误的数据?

标签 postgresql foreign-keys referential-integrity data-ingestion

数据库正在从流中提取数据,满足外键约束所需的所有行可能会迟到或永远不会到达。

这可能可以通过使用另一个没有外键约束的数据存储来完成,然后当所有需要的数据都可用时,读入具有 fk 约束的数据库。然而,这增加了复杂性,我想避免它。

我们正在开发一种解决方案,该解决方案创建“占位符”行来指向外键。当真实数据进入时,占位符将被替换为真实值。同样,这增加了复杂性,但这是迄今为止我们找到的最佳解决方案。

人们通常如何解决这个问题?

编辑:一些可能有助于解释问题的示例数据:

假设我们有这些表:

CREATE TABLE order (
  id INTEGER NOT NULL,
  order_number,
  PRIMARY KEY (id),
  UNIQUE (order_number)
);

CREATE TABLE line_item (
  id INTEGER NOT NULL,
  order_number INTEGER REFERENCES order(order_number),
  PRIMARY KEY (id)
);

如果我先插入订单,没问题!但假设我尝试过:

插入订单 123 之前插入 line_item (order_number) 值 (123)。这当然会使 fk 约束失效。但这可能是我获取数据的顺序,因为它是从从多个源收集这些数据的流中读取的。

此外,为了解决@philpxy的问题,我并没有真正找到太多相关内容。提到的一件事是 deferred constraints 。这是一种在事务结束时等待执行 fk 约束的机制。然而,我认为在我的情况下不可能做到这一点,因为只要收到数据,这些插入语句就会随机运行。

最佳答案

您遇到了业务工作流程问题,因为各个订单的行项目在订单本身进入之前就进入了。一种解决方法(可能并不理想)是创建一个插入前触发器,该触发器检查每个传入的插入line_item 表,该订单是否已存在于 order 表中。如果没有,那么它将首先插入订单记录,然后再尝试在 line_item 上插入。

CREATE OR REPLACE FUNCTION "public"."fn_insert_order" () RETURNS trigger AS $$
BEGIN
    INSERT INTO "order" (order_number)
    SELECT NEW.order_number
    WHERE NOT EXISTS (SELECT 1 FROM "order" WHERE order_number = NEW.order_number);
    RETURN NEW;
END
$$
LANGUAGE 'plpgsql'

# trigger 
CREATE TRIGGER "trigger_insert_order"
BEFORE INSERT ON line_item FOR EACH ROW
EXECUTE PROCEDURE fn_insert_order()

注意:我假设 order 表的 id 列实际上是自动递增的,在这种情况下,Postgres 在插入时会自动为其分配一个值多于。最有可能的是,这就是您想要的,因为拥有两个都需要手动分配的 id 列没有多大意义。

关于postgresql - 具有外键约束的关系数据库如何摄取顺序可能错误的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59728017/

相关文章:

sql - 在 Postgresql 中,如何按列选择前 n% 的行?

php - Laravel getRelations() 返回空白

MySQL 问题 1025

mysql - InnoDB 表被制作为 MyISAM

sql-server - 是否可以将参照完整性检查推迟到 SQL Server 中的事务结束?

ruby-on-rails - Rails 中的参照完整性

database - 如果表上有索引,如何处理表更新/插入

postgresql - Go database/sql 改变表名的大小写

sql - Magento 自定义模块中的完整性约束违规

php - postgres/pdo 查询绑定(bind)值错误