PostGIS & databases

Spatial data in Postgres: connecting, querying, and writing results back.

An unqualified table name resolved through the search path, and what happens when it is not found. a name in SQL is not an addressFROM parcelspg_catalog.parcels?public.parcels?raw.parcels ✓search_path, in orderno USAGE?"does not exist"Which is why "relation does not exist" can mean "you may not look" — and why you qualify the name

PostGIS is the right place for spatial data that several people share, that is larger than one person’s memory, or that needs an index somebody else maintains. Most of this topic is about the two seams: getting data in and out of Python, and getting the database to do the work rather than the client.

The recurring surprise is that a name in SQL is not an address. An unqualified table name is resolved through the search path, unquoted identifiers are folded to lower case, and permissions are two independent layers — so "relation does not exist" can genuinely mean "you may not look". The other recurring theme is arithmetic: keeping the indexed column bare so the index applies, and comparing rows in to rows out so a spatial join’s fan-out is noticed.

The concepts cover how geometry is stored and indexed; the how-to guides connect, query, write and upsert; and the fixes are the connection, permission and type errors that make up most of a first week with it.

Learning paths run through this topic too — see the end of this page.

🧭 Start with the concepts

The ideas the how-to guides below assume you already have.

⚙️ Then do the task

Step-by-step walkthroughs with code you can copy and adapt.

Show every how-to guide in this topic

🔧 When it breaks

The errors this topic produces, with the cause explained rather than just the command.

Related topics

Subjects that keep coming up alongside this one, most overlap first.

Keep browsing

PostGIS & databases sits in Tools. Every topic on the site is listed on the topics index.