【问题标题】:How to store point (x, y) in a database?如何在数据库中存储点(x,y)?
【发布时间】:2020-12-25 05:25:35
【问题描述】:

我需要在我的数据库中存储位置(x,y 点),其中点可以为空,XY 总是小于 999。目前我使用的是 EFCore Code First 和 Postgresql 数据库,但我想灵活一点,这样我就可以在没有太多工作的情况下切换到 MSSql。我不打算离开 EF Core。

现在,我有两列:LocationXLocationY,都是int? 类型。我不确定这是否是一个好的解决方案,因为从技术上讲 DB 允许 (X=2, Y=null),它应该是。要么都为空,要么都不是。

我的选择二是将它存储在一个字符串列中:“123x321”,最大长度为 7。

有没有更好的办法?

谢谢,

【问题讨论】:

  • 为什么不使用point
  • @a_horse_with_no_name 哦,我不知道这种类型。呃..但为什么它需要 16 个字节?使用两个 smallint 列,我可以将一个点存储在 4 个字节上
  • 在 PostgreSQL 和 MSSQL 中以统一的方式支持几何类型。见Spatial Data in EF Core。它们支持比简单的 X 和 Y 值更强大的查询。

标签: postgresql .net-core entity-framework-core ef-core-3.1


【解决方案1】:

检查约束可用于强制两个列同时为 NULL 或 NOT NULL:

CREATE TABLE t(id INT,
  x INT,
  y INT,
  CHECK((x IS NULL AND y IS NULL) OR (x IS NOT NULL AND y IS NOT NULL))
);

db<>fiddle demo

【讨论】:

    【解决方案2】:

    除了@LukaszSzozda 建议的检查约束之外,您还可以通过对每个值附加检查约束来限制 x,y 值。所以假设它们也必须在 0,999 范围内

    CREATE TABLE t(id INT,
      x INT constraint x_range check ( x>=0 and x<=999),
      y INT constraint y_range check ( y>=0 and y<=999),
      CHECK((x IS NULL AND y IS NULL) OR (x IS NOT NULL AND y IS NOT NULL))
    );
    

    就您存储单个字符串的想法而言 - 非常糟糕。您不仅会遇到每次需要它们时都分离值的问题,它还允许明显无效的数据。就数据库而言,值“1234567”甚至“abcdefg”都是完全有效的。 因此,您的表定义必须考虑并消除它们。这样你的表定义就变成了:

    create table txy
               ( xy_string varchar(7) 
               , constraint xy_format check( xy_string ~* '^\d{1,3}x\d{1,3}') 
               )
    insert into txy(xy_string) 
      ( values ('1x2'), ('354X512'), ('38x92') );
    

    这实际上是一个减少,因为它回到了单个约束,但是您的查询现在需要类似:

    select xy_string 
         , regexp_replace(xy_string, '^(\d+)(X|x)(\d+)','\1') x 
         , regexp_replace(xy_string, '^(\d+)(X|x)(\d+)','\3') y
    from txy;
    

    在此处查看demo

    简而言之,永远不要将数字值组存储为单个分隔字符串。额外的工作是不值得的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-02
      • 2018-06-08
      • 1970-01-01
      • 1970-01-01
      • 2011-09-03
      • 2022-01-19
      相关资源
      最近更新 更多