SPARQL
Content may include inaccuracies, outdated information, or technical errors. Users are advised to cross-check critical information before implementation.
SPARQL queries a model as RDF. It is one of the two languages that can change a model: a query reads, and a SPARQL Update writes, so a SPARQL body can back a quick fix.

Writing an expression
A SPARQL expression is one complete SPARQL operation - a query or an update. It
runs against the model that holds the contextual object, mapped to RDF, with
that object bound to ?self.
A rule states a yes-or-no question about ?self:
ASK { ?self archimate:Nameable.name ?name . FILTER(STRLEN(STR(?name)) > 0) }
You do not write the PREFIX lines. The standard rdf, rdfs, owl and xsd
prefixes are declared for you, and so is one prefix per metamodel in scope,
taken from the metamodel's own prefix - archimate for ArchiMate. You can still
declare your own; a declaration in the body wins.
Content assist proposes the variables already used in the body, the classes and properties of the metamodels in scope, and SPARQL keywords. After a variable in predicate position it offers properties first.
Query forms and what they return
| Form | Result |
|---|---|
ASK | a boolean |
SELECT | one row per solution |
CONSTRUCT | the triples the template produces |
DESCRIBE | the triples describing the named resources |
A SELECT that projects a single variable returns the values themselves, and a
value that is an object IRI comes back as the object, so you can click through
to it. A SELECT that projects several variables returns one line of
name=value pairs per solution.
Where a rule requires a boolean, the body must be an ASK. A SELECT in that
position is reported in the editor before it runs. Everywhere else any
well-formed operation is accepted.
Variables in scope
?self is the object the expression is evaluated against, bound to its object
IRI. Which object that is depends on where the expression runs - see
The expression console.
In an update, ?g is bound in addition, to the graph holding the model. Every
other variable in the body is a query variable that you bind yourself.
The RDF view of a model
An expression sees the model that holds ?self, and nothing else. Within it:
- an object is an IRI of the form
urn:uuid:<id>; ?o a archimate:BusinessActormatches the concrete class of an object, and only that class - supertypes produce no triple, so a pattern forarchimate:ArchimateElementmatches nothing;- a feature is addressed as
prefix:DeclaringClass.feature, so the name of a business actor isarchimate:Nameable.nameand the ends of a relationship arearchimate:ArchimateRelationship.sourceandarchimate:ArchimateRelationship.target; - an attribute is a literal holding the value in its string form, including
numbers, booleans and enumeration literals, so compare with
STR()and cast withxsd:integer()and friends when you need a number; - a reference is a triple whose object is the IRI of the target, and containment
is a reference like any other, so
archimate:Folder.elementsandarchimate:FolderContainer.folderswalk the model tree; - only features that are set produce triples, and derived and transient features
produce none -
incomingRelationshipsandoutgoingRelationshipsare transient, so reach a relationship throughsourceandtargetinstead; - an inverse reference is a pattern with the variable in object position:
?subject ?property ?selffinds everything pointing at?self.
Models as RDF describes the mapping in full.
In a query the triples are in the default graph, so a query needs no GRAPH
clause and a GRAPH clause matches nothing.
Changing a model
An update body describes the change a quick fix applies. The triples are in the
graph bound to ?g, and that is the only graph read back afterwards, so every
template and every pattern that touches the model goes inside GRAPH ?g:
DELETE { GRAPH ?g { ?self archimate:Nameable.name ?name } }
INSERT { GRAPH ?g { ?self archimate:Nameable.name ?trimmed } }
WHERE { GRAPH ?g { ?self archimate:Nameable.name ?name }
BIND(REPLACE(STR(?name), "^\\s+|\\s+$", "") AS ?trimmed) }
INSERT DATA and DELETE DATA take no variables at all, so ?self and ?g
cannot appear in them. Write INSERT { GRAPH ?g { ... } } WHERE { ... }
instead.
Several operations separated by ; run in order against the same graph, and
?self and ?g stay bound across all of them.
The difference between the graph before and after the update is applied to the model:
- adding or removing an attribute triple sets or unsets the attribute;
- adding or removing a reference triple links or unlinks two objects;
- adding an
rdf:typetriple whose subject is a fresh IRI creates an object of that class, and a containment reference to it attaches it to the model.BIND(UUID() AS ?new)mints the IRI. The class must be concrete; - removing the containment reference triple that holds an object detaches it from the model.
An addition that points at an object which does not exist is reported as a warning and left unapplied.
What a modifying body produces is a set of individual changes. Whether they are written straight to the model or held for you to approve one by one is set by the apply mode. See the apply mode.
Examples
Reading, where ?self is an ArchiMate element.
The element carries a name:
ASK { ?self archimate:Nameable.name ?name . FILTER(STRLEN(STR(?name)) > 0) }
The element is connected to something:
ASK {
{ ?r archimate:ArchimateRelationship.source ?self }
UNION
{ ?r archimate:ArchimateRelationship.target ?self }
}
The element carries an owner property exactly once:
ASK {
{ SELECT (COUNT(?p) AS ?owners) WHERE {
?self archimate:Properties.properties ?p .
?p archimate:Property.key "owner" .
} }
FILTER(?owners = 1)
}
A documented element must also be named:
ASK {
FILTER NOT EXISTS {
?self archimate:Documentable.documentation ?doc .
FILTER(STRLEN(STR(?doc)) > 0)
FILTER NOT EXISTS { ?self archimate:Nameable.name ?name .
FILTER(STRLEN(STR(?name)) > 0) }
}
}
Names follow a convention:
ASK {
?self archimate:Nameable.name ?name .
FILTER(REGEX(STR(?name), "^[A-Z][A-Za-z ]*$"))
}
Everything this element realizes:
SELECT ?target WHERE {
?r a archimate:RealizationRelationship ;
archimate:ArchimateRelationship.source ?self ;
archimate:ArchimateRelationship.target ?target .
}
Everything that points at this element:
SELECT ?subject ?property WHERE { ?subject ?property ?self }
Everything reachable from this element by following relationships forwards:
SELECT DISTINCT ?reached WHERE {
?self (^archimate:ArchimateRelationship.source/archimate:ArchimateRelationship.target)+ ?reached
}
Elements filed in a folder that no relationship touches:
SELECT ?element WHERE {
?folder archimate:Folder.elements ?element .
FILTER NOT EXISTS { ?r archimate:ArchimateRelationship.source ?element }
FILTER NOT EXISTS { ?r archimate:ArchimateRelationship.target ?element }
}
How many objects of each class the model holds:
SELECT ?class (COUNT(?object) AS ?count) WHERE { ?object a ?class }
GROUP BY ?class
ORDER BY DESC(?count)
Modifying, where ?self is an ArchiMate element.
Give the element an owner property when it has none:
INSERT { GRAPH ?g { ?self archimate:Properties.properties ?new .
?new a archimate:Property ;
archimate:Property.key "owner" ;
archimate:Property.value "unassigned" } }
WHERE { BIND(UUID() AS ?new)
FILTER NOT EXISTS { GRAPH ?g {
?self archimate:Properties.properties ?p .
?p archimate:Property.key "owner" } } }
Fill in a placeholder documentation when there is none:
INSERT { GRAPH ?g { ?self archimate:Documentable.documentation "To be documented" } }
WHERE { FILTER NOT EXISTS { GRAPH ?g {
?self archimate:Documentable.documentation ?doc } } }
Detach the element and everything that refers to it:
DELETE WHERE { GRAPH ?g { ?self ?p ?o } } ;
DELETE WHERE { GRAPH ?g { ?s ?r ?self } }
SPARQL reference
The full SPARQL 1.1 Query and Update grammar is accepted, with the RDF-star triple terms of the query engine on top of it.
Query forms
| Syntax | Returns | Meaning |
|---|---|---|
SELECT ?a ?b WHERE { ... } | rows | the listed variables, one row per solution |
SELECT * WHERE { ... } | rows | every variable used in the pattern |
SELECT (expr AS ?v) WHERE { ... } | rows | a computed value under a new name |
SELECT DISTINCT ... | rows | duplicate solutions removed |
SELECT REDUCED ... | rows | duplicates may be removed |
ASK { ... } | boolean | whether the pattern has at least one solution |
CONSTRUCT { ... } WHERE { ... } | triples | the template, instantiated per solution |
CONSTRUCT WHERE { ... } | triples | the pattern itself as the template |
DESCRIBE ?v WHERE { ... } | triples | a description of each bound resource |
DESCRIBE <iri> | triples | a description of a named resource |
Update forms
| Syntax | Meaning |
|---|---|
INSERT DATA { GRAPH <g> { ... } } | add ground triples; no variables allowed, so ?self and ?g cannot be used |
DELETE DATA { GRAPH <g> { ... } } | remove ground triples; no variables allowed |
INSERT { ... } WHERE { ... } | add the template once per solution |
DELETE { ... } WHERE { ... } | remove the template once per solution |
DELETE { ... } INSERT { ... } WHERE { ... } | remove and add in one operation |
DELETE WHERE { ... } | remove exactly what the pattern matched |
WITH <g> DELETE { ... } INSERT { ... } WHERE { ... } | name the target graph once for the whole operation |
USING <g> | build the graph the WHERE clause reads from |
USING NAMED <g> | make a graph addressable through GRAPH in the WHERE clause |
LOAD <url> / LOAD <url> INTO GRAPH <g> | read an RDF document from a URL into a graph |
LOAD SILENT <url> | the same, without failing when the document cannot be read |
CLEAR GRAPH <g> / CLEAR DEFAULT / CLEAR NAMED / CLEAR ALL | remove all triples from graphs |
DROP GRAPH <g> / DROP DEFAULT / DROP NAMED / DROP ALL | remove graphs |
CREATE GRAPH <g> | create an empty graph |
ADD <g1> TO <g2> | copy the triples of one graph into another |
COPY <g1> TO <g2> | replace the contents of a graph with another's |
MOVE <g1> TO <g2> | as COPY, then drop the source |
<op> ; <op> | run operations in sequence |
CLEAR, DROP, CREATE, ADD, COPY and MOVE name graphs by IRI and
accept ?g nowhere, so they cannot be aimed at the model's graph. Triples
written anywhere other than ?g are discarded when the update finishes.
Prologue and dataset
| Syntax | Meaning |
|---|---|
PREFIX p: <namespace> | bind a CURIE prefix |
BASE <iri> | set the base for relative IRIs |
FROM <g> | build the default graph from the named graphs listed |
FROM NAMED <g> | make a graph addressable through GRAPH |
A query reads the model from the default graph, so a FROM or FROM NAMED
clause selects a graph the query does not have.
Graph patterns
| Syntax | Meaning |
|---|---|
?s ?p ?o . | a triple pattern |
?s ?p ?o1, ?o2 . | two objects for the same subject and predicate |
?s ?p1 ?o1 ; ?p2 ?o2 . | two predicates for the same subject |
?s a <Class> | shorthand for rdf:type |
{ ... } | a group |
GRAPH ?g { ... } | match inside a named graph |
OPTIONAL { ... } | match if possible, leaving variables unbound otherwise |
{ ... } UNION { ... } | solutions of either side |
MINUS { ... } | drop solutions compatible with the right side |
FILTER(expr) | keep solutions for which the expression is true |
FILTER EXISTS { ... } | keep solutions for which the pattern matches |
FILTER NOT EXISTS { ... } | keep solutions for which it does not |
BIND(expr AS ?v) | bind a computed value |
VALUES ?v { "a" "b" } | supply candidate values for one variable |
VALUES (?a ?b) { ("x" 1) ("y" 2) } | supply rows of values for several variables |
VALUES (?a ?b) { ("x" UNDEF) } | leave a variable of a row unbound |
{ SELECT ... WHERE { ... } } | a subquery, evaluated first |
SERVICE <endpoint> { ... } | delegate the pattern to a remote SPARQL endpoint |
SERVICE SILENT <endpoint> { ... } | the same, ignoring a failure of the remote endpoint |
[ ?p ?o ] | a blank node described inline |
( ?a ?b ) | an RDF collection |
Property paths
| Syntax | Meaning |
|---|---|
iri | one step along a property |
^iri | one step backwards - the inverse reference |
p1/p2 | a sequence of steps |
p1|p2 | either path |
p* | zero or more steps |
p+ | one or more steps |
p? | zero or one step |
!iri | any property other than this one |
!(p1|p2) | any property outside the set |
(p) | grouping |
This path walks the relationship graph forwards to any depth:
?self (^archimate:ArchimateRelationship.source/
archimate:ArchimateRelationship.target)+ ?reached
Solution modifiers
| Syntax | Meaning |
|---|---|
ORDER BY ?v | sort ascending by a variable |
ORDER BY ASC(expr), ORDER BY DESC(expr) | sort by a computed key |
GROUP BY ?v | group solutions before aggregating |
GROUP BY (expr AS ?v) | group by a computed key |
HAVING(expr) | keep groups for which the expression is true |
LIMIT n | at most n rows |
OFFSET n | skip the first n rows |
Operators
Highest precedence first.
| Syntax | Returns | Meaning |
|---|---|---|
!a, +a, -a | boolean, number | negation, sign |
a * b, a / b | number | multiplication, division |
a + b, a - b | number | addition, subtraction |
a = b, a != b | boolean | value equality and inequality |
a < b, a <= b, a > b, a >= b | boolean | ordering |
a IN (x, y) | boolean | membership in a list |
a NOT IN (x, y) | boolean | absence from a list |
a && b | boolean | conjunction |
a || b | boolean | disjunction |
Literals and terms
| Syntax | Meaning |
|---|---|
<http://example.org/x> | an absolute IRI |
prefix:local | a CURIE against a declared prefix |
a | rdf:type |
?v, $v | a variable |
"text", 'text' | a string literal |
"""text""", '''text''' | a string literal that may span lines |
"text"@en | a literal with a language tag |
"5"^^xsd:integer | a literal with an explicit datatype |
42, -3 | an integer literal |
4.5 | a decimal literal |
1.0e6 | a double literal |
true, false | a boolean literal |
_:b1 | a named blank node |
[] | an anonymous blank node |
() | rdf:nil, the empty collection |
# text | a comment to the end of the line |
<<?s ?p ?o>> | a triple term |
Term functions, testing and conversion
| Syntax | Returns | Meaning |
|---|---|---|
STR(term) | string | the lexical form of a literal or IRI |
LANG(literal) | string | the language tag, empty when there is none |
LANGMATCHES(tag, range) | boolean | whether a language tag matches a range |
DATATYPE(literal) | IRI | the datatype of a literal |
BOUND(?v) | boolean | whether the variable has a value |
IRI(string), URI(string) | IRI | build an IRI from a string |
BNODE(), BNODE(string) | blank node | a fresh blank node |
UUID() | IRI | a fresh urn:uuid: IRI |
STRUUID() | string | a fresh UUID as a string |
isIRI(term), isURI(term) | boolean | whether the term is an IRI |
isBLANK(term) | boolean | whether the term is a blank node |
isLITERAL(term) | boolean | whether the term is a literal |
isNUMERIC(term) | boolean | whether the term is a numeric literal |
sameTerm(a, b) | boolean | term identity, stricter than = |
IF(cond, a, b) | any | conditional value |
COALESCE(a, b, ...) | any | the first argument that evaluates without error |
STRDT(string, iri) | literal | a literal with the given datatype |
STRLANG(string, tag) | literal | a literal with the given language tag |
xsd:string(v) | literal | cast to a string |
xsd:boolean(v) | literal | cast to a boolean |
xsd:integer(v), xsd:decimal(v), xsd:double(v), xsd:float(v) | literal | cast to a number |
xsd:long(v), xsd:int(v), xsd:short(v), xsd:byte(v) | literal | cast to a sized integer |
xsd:unsignedLong(v), xsd:unsignedInt(v), xsd:unsignedShort(v), xsd:unsignedByte(v) | literal | cast to an unsigned integer |
xsd:nonNegativeInteger(v), xsd:positiveInteger(v), xsd:nonPositiveInteger(v), xsd:negativeInteger(v) | literal | cast to a sign-constrained integer |
xsd:date(v), xsd:dateTime(v) | literal | cast to a date or a date and time |
String functions
| Syntax | Returns | Meaning |
|---|---|---|
STRLEN(s) | number | the number of characters |
SUBSTR(s, start) | string | from a one-based position to the end |
SUBSTR(s, start, length) | string | a fixed number of characters |
UCASE(s), LCASE(s) | string | case conversion |
STRSTARTS(s, prefix) | boolean | whether the string starts with the prefix |
STRENDS(s, suffix) | boolean | whether the string ends with the suffix |
CONTAINS(s, part) | boolean | whether the string contains the part |
STRBEFORE(s, part) | string | what precedes the first occurrence |
STRAFTER(s, part) | string | what follows the first occurrence |
ENCODE_FOR_URI(s) | string | percent-encode for use in a URI |
CONCAT(s1, s2, ...) | string | join the arguments |
REGEX(s, pattern) | boolean | whether the pattern matches |
REGEX(s, pattern, flags) | boolean | the same, with flags such as "i" |
REPLACE(s, pattern, replacement) | string | replace every match |
REPLACE(s, pattern, replacement, flags) | string | the same, with flags |
STRAFTER(STR(?name), "-") returns what follows the first hyphen of a name.
Numeric functions
| Syntax | Returns | Meaning |
|---|---|---|
ABS(n) | number | absolute value |
ROUND(n) | number | nearest integer |
CEIL(n) | number | smallest integer not less than n |
FLOOR(n) | number | largest integer not greater than n |
RAND() | number | a double between 0 and 1 |
Date and time functions
| Syntax | Returns | Meaning |
|---|---|---|
NOW() | dateTime | the current date and time |
YEAR(d), MONTH(d), DAY(d) | number | date components |
HOURS(d), MINUTES(d), SECONDS(d) | number | time components |
TIMEZONE(d) | duration | the timezone as a duration |
TZ(d) | string | the timezone as it is written |
Hash functions
| Syntax | Returns | Meaning |
|---|---|---|
MD5(s) | string | the MD5 digest as hexadecimal |
SHA1(s) | string | the SHA-1 digest |
SHA256(s) | string | the SHA-256 digest |
SHA384(s) | string | the SHA-384 digest |
SHA512(s) | string | the SHA-512 digest |
Triple term functions
These have no keyword form. Each is called by its IRI, written with the rdf
prefix that is already declared.
| Syntax | Returns | Meaning |
|---|---|---|
rdf:Statement(s, p, o) | triple term | build a triple term |
rdf:isTriple(t) | boolean | whether the term is a triple term |
rdf:subject(t) | term | the subject of a triple term |
rdf:predicate(t) | IRI | the predicate of a triple term |
rdf:object(t) | term | the object of a triple term |
Aggregates
| Syntax | Returns | Meaning |
|---|---|---|
COUNT(?v) | number | the number of bound values |
COUNT(*) | number | the number of solutions in the group |
COUNT(DISTINCT ?v) | number | the number of distinct values |
SUM(?v), AVG(?v) | number | total and mean |
MIN(?v), MAX(?v) | any | smallest and largest value |
SAMPLE(?v) | any | one value from the group |
GROUP_CONCAT(?v) | string | the values joined by a space |
GROUP_CONCAT(?v; SEPARATOR=", ") | string | the values joined by a given separator |
DISTINCT may be written inside any aggregate, as in
GROUP_CONCAT(DISTINCT ?name; SEPARATOR=", ").
Four further aggregates have no keyword form and are called by their IRI:
| Syntax | Returns | Meaning |
|---|---|---|
<http://rdf4j.org/aggregate#stdev>(?v) | number | sample standard deviation |
<http://rdf4j.org/aggregate#stdev_population>(?v) | number | population standard deviation |
<http://rdf4j.org/aggregate#variance>(?v) | number | sample variance |
<http://rdf4j.org/aggregate#variance_population>(?v) | number | population variance |