Postgresql 是否可以使用纬度和经度的舍入值向Postgres表添加约束?

Postgresql 是否可以使用纬度和经度的舍入值向Postgres表添加约束?,postgresql,Postgresql,我有一个存储纬度和经度数据的表。如下所示: CREATE TABLE geo_sample ( id uuid DEFAULT uuid_generate_v4 (), latitude FLOAT NOT NULL, longitude FLOAT NOT NULL, PRIMARY KEY (id) ); 过了一段时间,我们意识到我们不希望输入彼此太近的地理坐标,因此我们认为可以使用约束来帮助执行此操作。我的想法是,如果我们将坐标四舍五入到小数点后n位,这将确保地理坐标不

我有一个存储纬度和经度数据的表。如下所示:

CREATE TABLE geo_sample
( 
  id uuid DEFAULT uuid_generate_v4 (),
  latitude FLOAT NOT NULL,
  longitude FLOAT NOT NULL,
  PRIMARY KEY (id)
);
过了一段时间,我们意识到我们不希望输入彼此太近的地理坐标,因此我们认为可以使用约束来帮助执行此操作。我的想法是,如果我们将坐标四舍五入到小数点后n位,这将确保地理坐标不会堆积得太紧密

我试过这个:

ALTER TABLE geo_sample
ADD CONSTRAINT unique_areas UNIQUE (ROUND(latitude::numeric, 3), ROUND(longitude::numeric, 3));
但这不起作用——这是一个语法错误

在这种情况下,我能够通过使用唯一索引实现我想要的:

CREATE UNIQUE INDEX unique_areas ON geo_sample (ROUND(latitude::numeric, 3), ROUND(longitude::numeric, 3));
请注意,我必须强制纬度和经度为数字,否则函数签名(?)会出错。仅供参考:如果存在违反条件的行,此操作将失败,并显示一条非常常见的错误消息“无法创建唯一索引”


我的问题是:是否可以使用约束而不是索引来实现这一点?更广泛地说,什么时候可以使用修改函数(如
LOWER()
以避免重复的电子邮件地址)来帮助强制执行数据完整性?

您可以创建一个用于约束的函数

CREATE FUNCTION no_similar_XY_in_my_data(x float, y float)
RETURNS boolean AS $$
SELECT NOT EXISTS (
  SELECT 1 FROM geo_sample 
    WHERE round(geo_sample.latitude::numeric,3) = round(y::numeric,3) AND  round(geo_sample.longitude::numeric,3) = round(x::numeric,3)
  );
$$ LANGUAGE sql;

ALTER TABLE geo_sample ADD CONSTRAINT no_similar_XY CHECK (no_similar_XY_in_my_data(longitude,latitude));

insert into geo_sample(longitude,latitude) values (1.23456, 9.876543);
INSERT 0 1
insert into geo_sample(longitude,latitude) values (1.23456, 9.876543);
ERROR:  new row for relation "geo_sample" violates check constraint "no_similar_xy"
DETAIL:  Failing row contains (2, 9.876543, 1.23456).
这就是说,将协调的位置四舍五入将确保两个位置不相互靠近。使用3位小数的四舍五入,0.12349999将四舍五入为0.123,而0.12350000000将四舍五入为0.124,尽管这两个点几乎位于同一位置

正确的方法是使用PostGIS扩展,将点保存为几何体,并计算点之间的实际距离。此函数也可用于检查约束

CREATE FUNCTION no_nearby_point_in_my_data(g geometry)
RETURNS boolean AS $$
SELECT NOT EXISTS (
  SELECT 1 FROM geo_sample 
  WHERE ST_DWithin( my_data.geom, g, 0.001));
$$ LANGUAGE sql;

无论出于何种目的,唯一索引都和唯一约束一样好。不,每个
unique
约束都需要一个索引来支持。@Bergi:我很确定每个unique约束都会在后台创建一个唯一索引。不确定
ST_DWithin()
是否支持必要的GIST运算符,但如果它支持,排除约束可能比使用函数的检查约束更有效。要澄清,引用函数(内置或自定义函数),似乎只能使用
创建唯一索引
,而不能使用
添加约束
语法,对吗?(即使在幕后它们可能是等价的?@Everett否,我提供的示例使用了
add constraint