En cas de maintenance correcte de la géodatabase versionnée éditée (maintenance régulière par compression et compression complète), ni l'administrateur de base de données ni l'administrateur SDE ne devraient avoir besoin de consulter la table des états. C'est une table système entièrement contrôlée par le système ArcGIS.
Cependant, pour des raisons éducatives (qui peuvent être utiles dans des enquêtes), il n'est pas mauvais de jeter un œil à la table des états de temps en temps (par exemple lors des éditions). Ce qui est essentiellement le plus intéressant dans la table des états, c'est la liaison de l'état donné à son état parent via l'attribut parent_state_id (structure arborescente hiérarchique) montrant où une édition a provoqué une bifurcation, mais malheureusement ce n'est pas très clair dans la table relationnelle.
L'arbre des états dans la table sde.states n'est pas très intuitif dans une vue standard.
Les bases de données relationnelles ont cependant leurs méthodes pour travailler avec des structures hiérarchiques, permettant de manipuler les données hiérarchiques dans les requêtes SELECT et d'ajuster les données pour l'affichage.
Par exemple, Oracle propose la clause START WITH/CONNECT BY, qui permet un parcours récursif de la table basé sur la liaison à l'élément parent, ainsi que des fonctions qui fournissent des informations sur la position d'un élément dans l'arbre. Par exemple, LEVEL indique le niveau d'imbrication dans la récursion (c'est-à-dire le nombre de liens vers l'élément initial) ou SYS_CONNECT_BY_PATH retourne la liste des éléments parents ordonnés du point de départ jusqu'à l'élément donné.
SELECT
--formatage du résultat global (indentation selon le niveau dans l'arbre d'états, ajout de l'état parent)
LPAD(t.state_id, 2* t."LEVEL" + 1 , ' ')|| '(' || t.parent_state_id || ')' "state(parent state)",
ver.owner || '.' || ver.name "version"
FROM
(
--ajout dans la récursion du point exclu où state_id = parent_state_id
SELECT
state_id,
parent_state_id,
0 "LEVEL",
'/0' PATH_STR
FROM
sde.states
WHERE
parent_state_id = 0
AND state_id = parent_state_id
UNION ALL
SELECT
state_id,
parent_state_id,
LEVEL, --obtention du niveau dans l'arbre d'états
SYS_CONNECT_BY_PATH(state_id, '/') AS PATH_STR --obtention du chemin state_id depuis le début jusqu'à l'état spécifique
FROM
sde.states
START WITH --il faut exclure state_id = 0 qui a parent_state_id lui-même pour éviter les boucles infinies
parent_state_id = 0
AND state_id != parent_state_id
CONNECT BY
PRIOR state_id = parent_state_id --la connexion récursive se fait via le lien parent_state_id
) t
LEFT OUTER JOIN sde.versions ver ON --jointure pour obtenir les informations sur les états des versions spécifiques
ver.state_id = t.state_id
ORDER BY --tri selon la ligne parentale de l'état
t.PATH_STR
Exemple de requête formatant récursivement l'arborescence des états depuis la table sde.states.
Une requête conçue ainsi sur la table des états (et des versions) formate déjà clairement l'arborescence des états :
Postgresql dispose certes de fonctions similaires connectby pour l'extension tablefunc, mais celle-ci n'est pas activée par défaut et un administrateur SDE peut ne pas avoir les droits nécessaires.
Cela ne signifie pas qu'un administrateur SDE ne peut pas afficher l'arborescence des états sans cette extension. Il est possible d'utiliser la clause WITH RECURSIVE, où une jointure récursive similaire est effectuée sur la table elle-même. Comme Oracle (avec LEVEL et SYS_CONNECT_BY_PATH), Postgresql offre aussi des fonctions retournant des informations sur la position dans l'arbre DEPTH' et 'PATH :
with recursive cte(state_id, parent_state_id, depth) as (
--ajout dans la récursion du point exclu où state_id = parent_state_id
select
state_id,
parent_state_id,
0
from
sde.sde_states
where
parent_state_id = state_id
union all
select
sde.sde_states.state_id,
sde.sde_states.parent_state_id,
cte.depth + 1
from
sde.sde_states
inner join cte
on
sde.sde_states.parent_state_id = cte.state_id --la connexion récursive se fait via le lien parent_state_id
)
cycle state_id -- détection de cycle pour éviter les boucles infinies dans la jointure
set
'is_cycle'
' using 'path' -- ajout de toute la ligne parentale de l'élément depuis le point initial jusqu'à cet élément',' field 82':',',' field 83':'cte2 as ',' field 84':'(',' field 85':'select',' field 86':' state_id,',' field 87':' parent_state_id,',' field 88':' depth,',' field 89':' path',' field 90':' from',' field 91':'
,
cte2 as
(
select
state_id,
parent_state_id,
depth,
path
from
"cte"
where --vyloučení nekonečných smyček
not "is_cycle")
select
--formátování celkového výstupu (odsazení dle úrovně ve stromu stavu, připojení parent state)
lpad( cast(cte2.state_id as text) , 2 * depth + 1, ' ')|| '(' || cte2.parent_state_id || ')' "state(parent state)",
ver.owner || '.' || ver.name "version"
from
cte2
--najoinování informace o stavech konkrétních verzí
left outer join sde.sde_versions ver on
cte2.state_id = ver.state_id
order by --seřazení dle rodičovské linie stavu
path
Ukázka postgresql dotazu formátujícího strom stavu do podoby shodné s oracle dotazem.
Uvedené dotazy je možné joinem rozšířit o další informace (například joinem sde.state_locks a sde.process_information o stavy uzamčené editacemi).
Další informace o hierarchických dotazech lze získat přímo v dokumentaci:
https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/Hierarchical-Queries.html#GUID-0118DF1D-B9A9-41EB-8556-C6E7D6A5A84E
https://www.enterprisedb.com/postgres-tutorials/how-run-hierarchical-queries-oracle-and-postgresql
https://www.enterprisedb.com/blog/oracle-postgresql-start-withconnect
https://www.postgresql.org/docs/18/queries-with.html