我使用的是postGIS,而且我对SQL不是很熟悉。
只要我这样做(伪代码!),我就可以成功插入到我的markers
表中:
'INSERT INTO markers(created_by, title, description, lat, lng, geography)\
values($1, $2, $3, $4::decimal, $5::decimal, ST_SetSRID(ST_MakePoint($5::decimal, $4::decimal), $6))',
[
data.created_by,
data.title,
data.description,
data.lat,
data.lng,
4326
]'
如您所见,我正在从我的应用程序代码中执行ST_SetSRID(ST_MakePoint($5::decimal, $4::decimal), $6)
。
我想避免这种情况,而是把它放在数据库端。由于我可以在数据库端执行自动时间戳等操作,因此我想知道我是否也可以在桌面上执行ST_SetSRID(ST_MakePoint(lng, lat), 4326)
。
这样,应用程序只需要提供lat和lng,数据库就会执行ST_SetSRID(ST_MakePoint())
操作。
由于
编辑:由于两者都提供了非常好的帮助和建议,我不确定其标记为+1的答案。我希望未来的读者能够阅读并希望学到一些东西!
答案 0 :(得分:2)
您可以使用触发器执行此操作。您的插入调用不会处理几何,只处理lat-long和其他非空间字段,触发器函数将创建几何。让我们不要忘记在更新行时也这样做。
请注意,我已对SRID进行了硬编码,因为无法将额外的动态参数传递给触发器功能。如果需要,请在表格中添加一个字段以保存此值,您可以将其称为new.srid
CREATE OR REPLACE FUNCTION markers_geog_tg_fn() RETURNS trigger AS
$BODY$BEGIN
IF TG_OP = 'INSERT' AND (NEW.lat ISNULL or NEW.lng ISNULL ) THEN
RETURN NEW; -- no geometry
ELSIF TG_OP = 'UPDATE' THEN
--Lat Long updated to null, erase geometry
IF NEW.lat ISNULL or NEW.lng ISNULL THEN
NEW.geography = NULL;
END IF;
IF NEW.lat IS NOT DISTINCT FROM OLD.lat and NEW.lng IS NOT DISTINCT FROM OLD.lng THEN
RETURN NEW; -- same old geometry
END IF;
END IF;
-- Attempt to transform a geometry
BEGIN
NEW.geography := ST_SetSRID(ST_MakePoint(NEW.lng::decimal, NEW.lat::decimal), 4326))
EXCEPTION WHEN SQLSTATE 'XX000' THEN
RAISE WARNING 'geography not updated: %', SQLERRM;
END;
RETURN NEW;
END;$BODY$ LANGUAGE plpgsql;
CREATE TRIGGER markers_geog_tg BEFORE INSERT OR UPDATE
ON markers FOR EACH ROW
EXECUTE PROCEDURE markers_geog_tg_fn();
答案 1 :(得分:1)
我想避免这种情况,而是把它放在数据库端。由于我可以在数据库端执行自动时间戳等操作,我想知道我是否也可以在表本身上执行
ST_SetSRID(ST_MakePoint(lng, lat), 4326)
。
它真的不是一个好主意,我知道这听起来像个好主意,但似乎很有吸引力。也就是说,你做的工作比你需要的还多。
CREATE TABLE markers (geom geography(POINT,4326) );
INSERT INTO markers(geom) VALUES (ST_MakePoint(0,0));
正如您在此处所见,geography
的默认SRID为4326.您不必将其设置为4326,但显式不会受到伤害。此外,将输入转换为ST_MakePoint()
为十进制是坏的想法。 ST_MakePoint
仅接受double precision
。来自\df ST_MakePoint
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+--------------+------------------+------------------------------------------------------------------------+--------
public | st_makepoint | geometry | double precision, double precision | normal
public | st_makepoint | geometry | double precision, double precision, double precision | normal
public | st_makepoint | geometry | double precision, double precision, double precision, double precision | normal
所以你可以在这里看到额外演员实际上只是增加了更多的工作。您真正想要的只是ST_MakePoint(lng,lat)
列中的简单geography(POINT,4326)
。
其余任务需要触发器。它还需要一个额外的列lat和long。 虽然我可以告诉你如何这样做,但我强烈建议不这样做。
ALTER TABLE markers
ADD COLUMN lat double precision,
ADD COLUMN long double precision;
CREATE OR REPLACE FUNCTION do_stupid_stuff()
RETURNS trigger
AS $$
BEGIN
NEW.geom = ST_MakePoint(NEW.long, NEW.lat);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER really_lazy
AFTER INSERT ON markers
FOR EACH ROW
EXECUTE PROCEDURE do_stupid_stuff();