Skip to main content

SPARQL

This document was generated using AI assistance

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.

A SPARQL query in the console, answered with a row per name it selects

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

FormResult
ASKa boolean
SELECTone row per solution
CONSTRUCTthe triples the template produces
DESCRIBEthe 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:BusinessActor matches the concrete class of an object, and only that class - supertypes produce no triple, so a pattern for archimate:ArchimateElement matches nothing;
  • a feature is addressed as prefix:DeclaringClass.feature, so the name of a business actor is archimate:Nameable.name and the ends of a relationship are archimate:ArchimateRelationship.source and archimate: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 with xsd: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.elements and archimate:FolderContainer.folders walk the model tree;
  • only features that are set produce triples, and derived and transient features produce none - incomingRelationships and outgoingRelationships are transient, so reach a relationship through source and target instead;
  • an inverse reference is a pattern with the variable in object position: ?subject ?property ?self finds 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:type triple 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

SyntaxReturnsMeaning
SELECT ?a ?b WHERE { ... }rowsthe listed variables, one row per solution
SELECT * WHERE { ... }rowsevery variable used in the pattern
SELECT (expr AS ?v) WHERE { ... }rowsa computed value under a new name
SELECT DISTINCT ...rowsduplicate solutions removed
SELECT REDUCED ...rowsduplicates may be removed
ASK { ... }booleanwhether the pattern has at least one solution
CONSTRUCT { ... } WHERE { ... }triplesthe template, instantiated per solution
CONSTRUCT WHERE { ... }triplesthe pattern itself as the template
DESCRIBE ?v WHERE { ... }triplesa description of each bound resource
DESCRIBE <iri>triplesa description of a named resource

Update forms

SyntaxMeaning
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 ALLremove all triples from graphs
DROP GRAPH <g> / DROP DEFAULT / DROP NAMED / DROP ALLremove 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

SyntaxMeaning
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

SyntaxMeaning
?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

SyntaxMeaning
irione step along a property
^irione step backwards - the inverse reference
p1/p2a sequence of steps
p1|p2either path
p*zero or more steps
p+one or more steps
p?zero or one step
!iriany 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

SyntaxMeaning
ORDER BY ?vsort ascending by a variable
ORDER BY ASC(expr), ORDER BY DESC(expr)sort by a computed key
GROUP BY ?vgroup solutions before aggregating
GROUP BY (expr AS ?v)group by a computed key
HAVING(expr)keep groups for which the expression is true
LIMIT nat most n rows
OFFSET nskip the first n rows

Operators

Highest precedence first.

SyntaxReturnsMeaning
!a, +a, -aboolean, numbernegation, sign
a * b, a / bnumbermultiplication, division
a + b, a - bnumberaddition, subtraction
a = b, a != bbooleanvalue equality and inequality
a < b, a <= b, a > b, a >= bbooleanordering
a IN (x, y)booleanmembership in a list
a NOT IN (x, y)booleanabsence from a list
a && bbooleanconjunction
a || bbooleandisjunction

Literals and terms

SyntaxMeaning
<http://example.org/x>an absolute IRI
prefix:locala CURIE against a declared prefix
ardf:type
?v, $va variable
"text", 'text'a string literal
"""text""", '''text'''a string literal that may span lines
"text"@ena literal with a language tag
"5"^^xsd:integera literal with an explicit datatype
42, -3an integer literal
4.5a decimal literal
1.0e6a double literal
true, falsea boolean literal
_:b1a named blank node
[]an anonymous blank node
()rdf:nil, the empty collection
# texta comment to the end of the line
<<?s ?p ?o>>a triple term

Term functions, testing and conversion

SyntaxReturnsMeaning
STR(term)stringthe lexical form of a literal or IRI
LANG(literal)stringthe language tag, empty when there is none
LANGMATCHES(tag, range)booleanwhether a language tag matches a range
DATATYPE(literal)IRIthe datatype of a literal
BOUND(?v)booleanwhether the variable has a value
IRI(string), URI(string)IRIbuild an IRI from a string
BNODE(), BNODE(string)blank nodea fresh blank node
UUID()IRIa fresh urn:uuid: IRI
STRUUID()stringa fresh UUID as a string
isIRI(term), isURI(term)booleanwhether the term is an IRI
isBLANK(term)booleanwhether the term is a blank node
isLITERAL(term)booleanwhether the term is a literal
isNUMERIC(term)booleanwhether the term is a numeric literal
sameTerm(a, b)booleanterm identity, stricter than =
IF(cond, a, b)anyconditional value
COALESCE(a, b, ...)anythe first argument that evaluates without error
STRDT(string, iri)literala literal with the given datatype
STRLANG(string, tag)literala literal with the given language tag
xsd:string(v)literalcast to a string
xsd:boolean(v)literalcast to a boolean
xsd:integer(v), xsd:decimal(v), xsd:double(v), xsd:float(v)literalcast to a number
xsd:long(v), xsd:int(v), xsd:short(v), xsd:byte(v)literalcast to a sized integer
xsd:unsignedLong(v), xsd:unsignedInt(v), xsd:unsignedShort(v), xsd:unsignedByte(v)literalcast to an unsigned integer
xsd:nonNegativeInteger(v), xsd:positiveInteger(v), xsd:nonPositiveInteger(v), xsd:negativeInteger(v)literalcast to a sign-constrained integer
xsd:date(v), xsd:dateTime(v)literalcast to a date or a date and time

String functions

SyntaxReturnsMeaning
STRLEN(s)numberthe number of characters
SUBSTR(s, start)stringfrom a one-based position to the end
SUBSTR(s, start, length)stringa fixed number of characters
UCASE(s), LCASE(s)stringcase conversion
STRSTARTS(s, prefix)booleanwhether the string starts with the prefix
STRENDS(s, suffix)booleanwhether the string ends with the suffix
CONTAINS(s, part)booleanwhether the string contains the part
STRBEFORE(s, part)stringwhat precedes the first occurrence
STRAFTER(s, part)stringwhat follows the first occurrence
ENCODE_FOR_URI(s)stringpercent-encode for use in a URI
CONCAT(s1, s2, ...)stringjoin the arguments
REGEX(s, pattern)booleanwhether the pattern matches
REGEX(s, pattern, flags)booleanthe same, with flags such as "i"
REPLACE(s, pattern, replacement)stringreplace every match
REPLACE(s, pattern, replacement, flags)stringthe same, with flags

STRAFTER(STR(?name), "-") returns what follows the first hyphen of a name.

Numeric functions

SyntaxReturnsMeaning
ABS(n)numberabsolute value
ROUND(n)numbernearest integer
CEIL(n)numbersmallest integer not less than n
FLOOR(n)numberlargest integer not greater than n
RAND()numbera double between 0 and 1

Date and time functions

SyntaxReturnsMeaning
NOW()dateTimethe current date and time
YEAR(d), MONTH(d), DAY(d)numberdate components
HOURS(d), MINUTES(d), SECONDS(d)numbertime components
TIMEZONE(d)durationthe timezone as a duration
TZ(d)stringthe timezone as it is written

Hash functions

SyntaxReturnsMeaning
MD5(s)stringthe MD5 digest as hexadecimal
SHA1(s)stringthe SHA-1 digest
SHA256(s)stringthe SHA-256 digest
SHA384(s)stringthe SHA-384 digest
SHA512(s)stringthe 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.

SyntaxReturnsMeaning
rdf:Statement(s, p, o)triple termbuild a triple term
rdf:isTriple(t)booleanwhether the term is a triple term
rdf:subject(t)termthe subject of a triple term
rdf:predicate(t)IRIthe predicate of a triple term
rdf:object(t)termthe object of a triple term

Aggregates

SyntaxReturnsMeaning
COUNT(?v)numberthe number of bound values
COUNT(*)numberthe number of solutions in the group
COUNT(DISTINCT ?v)numberthe number of distinct values
SUM(?v), AVG(?v)numbertotal and mean
MIN(?v), MAX(?v)anysmallest and largest value
SAMPLE(?v)anyone value from the group
GROUP_CONCAT(?v)stringthe values joined by a space
GROUP_CONCAT(?v; SEPARATOR=", ")stringthe 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:

SyntaxReturnsMeaning
<http://rdf4j.org/aggregate#stdev>(?v)numbersample standard deviation
<http://rdf4j.org/aggregate#stdev_population>(?v)numberpopulation standard deviation
<http://rdf4j.org/aggregate#variance>(?v)numbersample variance
<http://rdf4j.org/aggregate#variance_population>(?v)numberpopulation variance

Further reading