简体   繁体   English

允许唯一键列使用空值作为键而不是忽略它

[英]allow unique key column to use null value as key instead of ignoring it

I am new to using graph ql, and I am trying to set up a unique key for one of my tables.我是使用 graph ql 的新手,我正在尝试为我的一个表设置一个唯一的键。

For context, the table's key will be determined on the combination of part_number + organization_id.对于上下文,表的键将根据 part_number + organization_id 的组合确定。 So each organization ID can only have one part_number, but different organizations can have the same part_number.所以每个组织ID只能有一个part_number,但不同的组织可以有相同的part_number。

The issue I am running into is that organization_id is a nullable field.我遇到的问题是 organization_id 是一个可为空的字段。 When null, this represents global data.当为 null 时,这表示全局数据。 So essentially, I want it to act the same as an organization_id.所以本质上,我希望它与 organization_id 一样。

IE, if I had the part_number: ABC123, I want to enforce that only one of those exist for each organization_id AND only one of those exists for a row with no organization_id. IE,如果我有 part_number:ABC123,我想强制每个 organization_id 只有其中一个存在,并且只有一个没有 organization_id 的行存在。

Currently, I have a unique key set to product_pn_organization_id, and everything works fine for products with an organization ID, but as soon as the organization ID is null graph ql completely ignores the unique key constraint.目前,我有一个唯一键设置为 product_pn_organization_id,并且对于具有组织 ID 的产品一切正常,但是一旦组织 ID 为空图 ql 就会完全忽略唯一键约束。 So when I run an insert mutation with the product_pn_organization_id constraint on a part_number: ABC123 organization_id: null (assuming this already exists) instead of updating the row, it creates a new row.因此,当我在 part_number: ABC123 organization_id: null 上运行带有 product_pn_organization_id 约束的插入突变时(假设它已经存在)而不是更新行,它会创建一个新行。

If I run the same insert with an organization_id (part_number: ABC123, organization_id: 1, again assuming this row already exists) it will update the columns instead of creating a new row.如果我使用 organization_id(part_number:ABC123,organization_id:1,再次假设该行已经存在)运行相同的插入,它将更新列而不是创建新行。

Right now, the only solution I can think of is creating an organization that represents 'global' and having that as the default organization_id so that organization_id is never actually null.现在,我能想到的唯一解决方案是创建一个代表“全球”的组织并将其作为默认的 organization_id,以便 organization_id 实际上永远不会为空。 However, I would rather avoid that if possible.但是,如果可能的话,我宁愿避免这种情况。

Hoping someone has some advice on how to move forward here.希望有人对如何在这里前进有一些建议。 Thanks!谢谢!

Per request, here are the mutations:根据请求,这里是突变:

This mutation inserts a new row with organization_id set to null.此更改会插入一个新行,其中 organization_id 设置为 null。

mutation MyMutation {
  insert_products(objects: {pn: "ABC123", manufacturer_pn: "MANABC123"}, on_conflict: {constraint: products_pn_organization_id_key, update_columns: manufacturer_pn}) {
    returning {
      id
    }
  }
}

Ideally, this query would update the row from the first query, but instead creates a new row.理想情况下,此查询将更新来自第一个查询的行,而不是创建一个新行。

mutation MyMutation {
  insert_products(objects: {pn: "ABC123", manufacturer_pn: "MANABC124"}, on_conflict: {constraint: products_pn_organization_id_key, update_columns: manufacturer_pn}) {
    returning {
      id
    }
  }
}

This query inserts the same PN but with an organization_id.此查询插入相同的 PN,但带有 organization_id。

mutation MyMutation {
  insert_products(objects: {pn: "ABC123", manufacturer_pn: "MANABC123", organization_id: "00000000-0000-0000-0000-000000000000"}, on_conflict: {constraint: products_pn_organization_id_key, update_columns: manufacturer_pn}) {
    returning {
      id
    }
  }
}

Unlike the second query, this query actually updates the row belonging to the organization_id/pn combination instead of creating a new row.与第二个查询不同,此查询实际上更新属于 organization_id/pn 组合的行,而不是创建新行。

mutation MyMutation {
  insert_products(objects: {pn: "ABC123", manufacturer_pn: "MANABC124", organization_id: "00000000-0000-0000-0000-000000000000"}, on_conflict: {constraint: products_pn_organization_id_key, update_columns: manufacturer_pn}) {
    returning {
      id
    }
  }
}

You are probably running on top of a Postgres DB, and you need to update to V 15 to get support for this.您可能在 Postgres 数据库之上运行,您需要更新到 V 15 以获得对此的支持。 More info here , and an excerpt:更多信息在这里,摘录:

In Postgres 14 and older versions unique constraints always treat NULL values as not equal to other NULL values.在 Postgres 14 和旧版本中,唯一约束总是将 NULL 值视为不等于其他 NULL 值。 If you're inserting a NULL value into a table and you have a unique constraint, the NULL value is considered to be distinct on its own.如果您要将 NULL 值插入到表中并且您具有唯一约束,则 NULL 值被认为是独立的。 NULL is always different from another NULL. NULL 总是不同于另一个 NULL。 When you're inserting five records into the "old_null_style" table where "val1" is just always the same value "Hello" and then "val2" is always NULL.当您向“old_null_style”表中插入五个记录时,其中“val1”始终是相同的值“Hello”,然后“val2”始终为 NULL。

Even though you have a unique constraint that actually supports you inserting that five times or as many times as you'd like, because you have that NULL value that makes each row distinct from another and because the unique constraint includes both "val1" and "val2", all the rows are unique.即使您有一个唯一约束实际上支持您插入五次或任意多次,因为您有 NULL 值使每一行与另一行不同,并且因为唯一约束包括“val1”和“ val2”,所有行都是唯一的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM