This folder documents the database tables of the SoilWise INSPIRE Soil (SO) GeoPackage, delivered as an OGC GeoPackage implemented on top of SQLite3. 1 The schema combines:
This page provides a technical entry point: how the schema is organised, which entities are central, and which integrity constraints and triggers are enforced.
Tip
Click the image to see it full‑size for better viewing.
Links are relative to the current directory (
documentation/tables/).
If your filenames differ (e.g.,soilsite/index.md), update the link targets only.
datastream.type (Quantity/Category/Boolean/Count/Text).A .gpkg file is an SQLite database that includes OGC GeoPackage metadata tables (e.g., gpkg_contents, gpkg_geometry_columns) to make layers directly usable in GIS software.
In this implementation:
gpkg_contents (per-table records),gpkg_geometry_columns,idx_soilsite_geom, idx_soilplot_geom).Spatial reference: the schema registers and uses ETRS89 / LAEA Europe (EPSG:3035) for the main geometry layers (e.g., Soil Site polygons, Soil Plot points, SoilBody geometry).
Most business tables expose a guid column (unique). If guid is NULL on INSERT, triggers generate a UUID-like lowercase value. Updates of guid are blocked by dedicated triggers.
Where required by the conceptual model, tables include:
validfrom / validto with checks enforcing validfrom <= validto,beginlifespanversion / endlifespanversion with consistency checks and automatic refresh of beginlifespanversion upon relevant updates.codelistMany domain attributes are not free text: triggers validate that the stored value exists in codelist.id for a given codelist.collection (e.g., SoilInvestigationPurposeValue, SoilPlotTypeValue, WRB/FAO codelists, and the local Category collection for categorical observations).
Implication: load the necessary codelist collections before inserting domain records.
The schema follows the operational flow widely used for soil field/legacy datasets:
soilsite)Represents an investigation area:
geometry),soilinvestigationpurpose validated against codelists.soilplot)Represents a plot / sampling location:
soilplotlocation),locatedon is a FK to soilsite(guid) (plot belongs to a site).soilprofile)Represents a soil profile, explicitly distinguishing:
isderived = 0): must have location NOT NULL,isderived = 1): must have location NULL.Observed profiles link to plots via location → soilplot(guid) (with cascade delete).
WRB classification fields are guarded by consistency checks and codelist membership rules (including version-dependent collections).
profileelement)Represents vertical subdivisions within a profile:
ispartof → soilprofile(guid) (cascade delete),profileelementtype encodes:
0 = Horizon1 = LayerTo manage soil measurements and indicators as time series, the schema implements:
datastream)Defines an observation stream:
name, definition, description),type constrained to {Quantity, Category, Boolean, Count, Text} with strict allowed combinations (UoM vs codespace vs bounds).sensor, observedproperty, optional observingprocedure (plus optional thing).guid_observingprocedure is present, the pair (procedure, observedProperty) must exist in obsprocedure_obsdproperty (enforced by triggers).observation)Stores individual results for a datastream:
guid_datastream and is unique per (phenomenontime_start, guid_datastream).result_real NOT NULL; bounds enforced if value_min/value_max set,result_text NOT NULL and must exist in codelist where collection = datastream.codespace,result_boolean ∈ {0,1}; other result fields NULL,result_real integer-like (numerically integral) plus bounds (if set),result_text NOT NULL; other result fields NULL.Additionally, observation triggers keep datastream.phenomenontime_start/end synchronised to the MIN/MAX of linked observations.
view_observationA dedicated view joins observations to their FOI context (site/plot/profile/element), and standardises output fields such as property name, procedure, UoM symbol, and type-specific numeric values. This is intended for reporting and extraction without re-implementing complex joins.
SELECT
ss.guid AS soilsite_guid,
sp.guid AS soilplot_guid,
pr.guid AS soilprofile_guid,
pe.guid AS profileelement_guid
FROM soilsite ss
JOIN soilplot sp ON sp.locatedon = ss.guid
JOIN soilprofile pr ON pr.location = sp.guid
LEFT JOIN profileelement pe ON pe.ispartof = pr.guid;