我有一个包含数百万行的postgres数据库,它有一个名为geom的列,它包含一个属性的边界.
使用python脚本我从该表中提取信息并将其重新插入到新表中.
当我在新表中插入时,脚本会出现以下错误:
Traceback (most recent call last): File "build_parcels.py", line 258, inmain() File "build_parcels.py", line 166, in main update_cursor.executemany("insert into parcels (par_id, street_add, title_no, proprietors, au_name, ua_name, geom) VALUES (%s, %s, %s, %s, %s, %s, %s)", inserts) psycopg2.IntegrityError: new row for relation "parcels" violates check constraint "enforce_geotype_geom"
新表有一个检查约束enforce_geotype_geom =((geometrytype(geom)='POLYGON':: text)或(geom IS NULL))而旧表没有,所以我猜测theres dud数据或非多边形(也许是多边形数据) ?)在旧表中.我想将新数据保持为多边形,因此不想插入任何其他内容.
最初我尝试使用标准的python错误处理来包装查询,希望dud geom行会失败,但脚本会继续运行,但脚本已被写入最后提交而不是每行,所以它不起作用.
我认为我需要做的是遍历旧表geom行并检查它们是什么类型的几何体,这样我就可以确定是否要保留它或者在插入新表之前将其丢弃
什么是最好的解决方法?
这个令人惊讶的PostGIS SQL有用,可以帮助你解决这个问题......这里有很多几何类型测试:
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- -- $Id: cleanGeometry.sql 2008-04-24 10:30Z Dr. Horst Duester $ -- -- cleanGeometry - remove self- and ring-selfintersections from -- input Polygon geometries -- http://www.sogis.ch -- Copyright 2008 SO!GIS Koordination, Kanton Solothurn, Switzerland -- Version 1.0 -- contact: horst dot duester at bd dot so dot ch -- -- This is free software; you can redistribute and/or modify it under -- the terms of the GNU General Public Licence. See the COPYING file. -- This software is without any warrenty and you use it at your own risk -- -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CREATE OR REPLACE FUNCTION cleanGeometry(geometry) RETURNS geometry AS $BODY$DECLARE inGeom ALIAS for $1; outGeom geometry; tmpLinestring geometry; Begin outGeom := NULL; -- Clean Process for Polygon IF (GeometryType(inGeom) = 'POLYGON' OR GeometryType(inGeom) = 'MULTIPOLYGON') THEN -- Only process if geometry is not valid, -- otherwise put out without change if not isValid(inGeom) THEN -- create nodes at all self-intersecting lines by union the polygon boundaries -- with the startingpoint of the boundary. tmpLinestring := st_union(st_multi(st_boundary(inGeom)),st_pointn(boundary(inGeom),1)); outGeom = buildarea(tmpLinestring); IF (GeometryType(inGeom) = 'MULTIPOLYGON') THEN RETURN st_multi(outGeom); ELSE RETURN outGeom; END IF; else RETURN inGeom; END IF; ------------------------------------------------------------------------------ -- Clean Process for LINESTRINGS, self-intersecting parts of linestrings -- will be divided into multiparts of the mentioned linestring ------------------------------------------------------------------------------ ELSIF (GeometryType(inGeom) = 'LINESTRING') THEN -- create nodes at all self-intersecting lines by union the linestrings -- with the startingpoint of the linestring. outGeom := st_union(st_multi(inGeom),st_pointn(inGeom,1)); RETURN outGeom; ELSIF (GeometryType(inGeom) = 'MULTILINESTRING') THEN outGeom := multi(st_union(st_multi(inGeom),st_pointn(inGeom,1))); RETURN outGeom; ELSIF (GeometryType(inGeom) = '' OR GeometryType(inGeom) = 'GEOMETRYCOLLECTION') THEN RETURN NULL; ELSE RAISE NOTICE 'The input type % is not supported %',GeometryType(inGeom),st_summary(inGeom); RETURN inGeom; END IF; End;$BODY$ LANGUAGE 'plpgsql' VOLATILE;