Postgis – Как проверить тип геометрии до того, как я сделаю вставку

У меня есть база данных postgres с миллионами строк, в ней есть столбец с именем geom, который содержит границу свойства.

используя скрипт python, я извлекаю информацию из этой таблицы и снова вставляю ее в новую таблицу.

когда я вставляю в новую таблицу, скрипт выдает следующее:

Traceback (most recent call last): File "build_parcels.py", line 258, in <module> main() 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" 

В новой таблице есть проверочное ограничение: принудительное_geotype_geom = ((geometrytype (geom) = 'POLYGON' :: text) OR (geom IS NULL), тогда как в старой таблице нет, поэтому я угадываю данные dud data или non polygon (возможно, многопользовательские данные ?) в старой таблице. Я хочу сохранить новые данные в виде многоугольника, поэтому не хочу вставлять что-либо еще.

Первоначально я попытался обернуть запрос стандартной обработкой ошибок python, надеясь, что строки dud geom потерпят неудачу, но скрипт будет продолжать работать, но сценарий был написан для фиксации в конце не каждой строки, поэтому он не работает.

Я думаю, что мне нужно сделать, это перебрать старые строки геометрии таблицы и проверить, какой тип геометрии они есть, поэтому я могу установить, хочу ли я ее сохранить или выбросить, прежде чем вставлять в новую таблицу

Каков наилучший способ обойти это?

3 Solutions collect form web for “Postgis – Как проверить тип геометрии до того, как я сделаю вставку”

Этот удивительно полезный бит 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) = '<NULL>' 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; 

Вариант 1 состоит в том, чтобы создать точку сохранения перед каждой вставкой и вернуться к этому безопасному месту, если INSERT завершится с ошибкой.

Вариант 2 заключается в том, чтобы прикрепить выражение ограничения проверки в качестве условия WHERE в исходном запросе, который создал данные, чтобы вообще не выбирать его.

Лучший ответ зависит от размера таблиц, относительного количества ошибочных строк и от того, как быстро и часто это должно выполняться.

Я думаю, вы можете использовать ST_CollectionExtract – Учитывая (мульти) геометрию, возвращает (мульти) геометрию, состоящую только из элементов указанного типа.

Я использую его при вставке результатов ST_Intersection, ST_Dump разбивает любые многополигональные коллекции на отдельные геометрии. Затем ST_CollectionExtract (theGeom, 3) отбрасывает ничего, кроме полигонов:

ST_CollectionExtract((st_dump(ST_Intersection(data.polygon, grid.polygon))).geom, )::geometry(polygon, 4326)

Второй параметр выше 3 может быть: 1 == POINT, 2 == LINESTRING, 3 == POLYGON

  • Escape SQL «LIKE» значение для Postgres с psycopg2
  • Обновление json-поля в Postgres
  • Ошибка утверждения: Django-rest-Framework
  • Не удается завершить флажок-миграцию
  • Как сделать поле в OpenERP необходимым только для определенного состояния рабочего процесса?
  • Выражение запроса Django для вычисленных полей, которые требуют условий и литья
  • django.db.utils.ProgrammingError: отношение уже существует
  • django.db.utils.OperationalError Не удалось подключиться к серверу
  • Python - лучший язык программирования в мире.