I have a table that stores latitude and longitude data. Something like the following:
CREATE TABLE geo_sample
(
id uuid DEFAULT uuid_generate_v4 (),
latitude FLOAT NOT NULL,
longitude FLOAT NOT NULL,
PRIMARY KEY (id)
);
After a while, we realized that we didn't want to allow geographical coordinates to be entered that are too close to one another, so we thought we could use a constraint to help enforce this. My thinking was that if we rounded the coordinates to n decimal places, that would ensure that the geographical coordinates would never be piled too closely on top of one another.
I tried this:
ALTER TABLE geo_sample
ADD CONSTRAINT unique_areas UNIQUE (ROUND(latitude::numeric, 3), ROUND(longitude::numeric, 3));
But that doesn't work -- it's a syntax error.
In this case, I was able to achieve what I wanted by using a unique index:
CREATE UNIQUE INDEX unique_areas ON geo_sample (ROUND(latitude::numeric, 3), ROUND(longitude::numeric, 3));
Note that I had to force the latitude and longitude to be numeric, otherwise it got an error about the function signature (?). FYI: this will fail with a very generic error message "could not create unique index" if there are rows present which violate the condition.
My question is: is it possible to do this using a constraint instead of an index? And more broadly, when is it ok to use modifying functions (like LOWER() to avoid duplicate email addresses) to help enforce data integrity?