SPARQL 1.2 查询语言

W3C 工作草案

关于本文档的更多详细信息
此版本:
https://www.w3.org/TR/2026/WD-sparql12-query-20260625/
最新发布版本:
https://www.w3.org/TR/sparql12-query/
最新编辑草案:
https://w3c.github.io/sparql-query/spec/
历史:
https://www.w3.org/standards/history/sparql12-query/
提交历史
测试套件:
https://w3c.github.io/rdf-tests/
最新推荐标准:
https://www.w3.org/TR/2013/REC-sparql11-query-20130321
编辑:
Olaf Hartig
Andy Seaborne
Ruben Taelman
Gregory Williams
Thomas Pellissier Tanon
前任编辑:
Steve Harris
Andy Seaborne
Eric Prud'hommeaux
反馈:
GitHub w3c/sparql-query拉取请求新建议题未关闭议题
public-rdf-star-wg@w3.org 主题行为 [sparql12-query] … 消息主题 …存档

摘要

RDF 是一种有向的、带标签的图数据模型,用于表示 Web 中的信息。本规范定义了用于 RDF 的 SPARQL 查询语言的语法和语义。SPARQL 可用于表达跨多种数据源的查询,无论数据是以 RDF 原生存储,还是通过中间件视为 RDF。SPARQL 具备查询必需和可选图模式及其合取与析取的能力。SPARQL 还支持聚合、子查询、否定、通过表达式创建值、可扩展的值测试,以及按源 RDF 图约束查询。SPARQL 查询 的结果可以是结果集,也可以是 RDF 图。

本文档状态

本节描述本文档在发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版可在 W3C 标准与草案 索引中找到。

本规范由 RDF Star 工作组发布,作为 格式与勘误规范更新的一部分。

本文档由 RDF & SPARQL 工作组 作为工作草案发布,并使用 推荐标准 轨道

作为 工作草案发布并不意味着获得 W3C 及其成员的认可。

这是一份草案文档,可能随时被其他文档更新、替换或废弃。 不应将本文档作为进行中的工作以外的内容引用。 对此即将推出的推荐标准的未来更新可能会纳入 新特性

本文档由一个按照 W3C 专利 政策运作的工作组产出。 W3C 维护着一份 任何专利 披露的公开列表, 这些披露与该工作组的交付物有关;该页面还包含 披露专利的说明。任何实际知晓某项专利,并认为该专利包含 必要权利要求 的个人,必须依照 W3C 专利政策第 6 节披露相关信息。

本文档受 2025年8月18日 W3C 流程文档管辖。

1. 简介

RDF 是一种有向的、带标签的图数据模型,用于表示 Web 中的信息。RDF 常用于表示个人信息、社交网络、关于数字制品的元数据等,也用于提供一种在异构 信息源之间进行集成的手段。本规范定义了用于 RDF 的 SPARQL 查询语言的语法和语义。

用于 RDF 的 SPARQL 查询语言旨在满足 RDF 数据访问工作组在 [RDF-DAWG-UC]、 SPARQL 1.1 工作组在 [SPARQL-FEATURES] 以及 RDF-star 工作组 所确定的用例和需求。

1.1 文档大纲

除非节标题中另有说明,本文档中的所有章节和附录均为规范性内容。

本文档的本节,即 第 1 节,介绍 SPARQL 查询语言规范。它说明本规范文档的组织结构,以及整个规范中使用的约定。

本规范的 第 2 节 通过一系列示例查询和查询结果介绍 SPARQL 查询语言本身。 第 3 节 通过更多示例继续介绍 SPARQL 查询语言, 这些示例展示 SPARQL 表达对出现在查询结果中的 RDF 项进行约束的能力。

第 4 节 展示 SPARQL 查询语言语法的细节。它是该语言完整文法 的配套说明,并定义语法结构如何表示 IRI、空白节点、字面量和变量。第 4 节还定义若干 语法结构的含义,这些结构作为更冗长表达式的语法糖。

第 5 节 介绍基本图模式和组图模式,它们是构造更复杂 SPARQL 查询模式的构建块。第 6、7 和 8 节展示将 SPARQL 图模式组合成更大图模式的结构。 具体而言,第 6 节 介绍将查询的一部分设为可选的能力; 第 7 节 介绍表达替代图模式析取的能力;并且 第 8 节 介绍用于测试信息缺失的模式。

第 9 节 为图模式匹配添加属性路径, 既为查询提供紧凑表示,也提供在图中匹配任意长度路径的能力。

第 10 节 描述 SPARQL 中可能的赋值形式。

第 11 节 介绍对结果进行分组和聚合的机制, 这些机制可作为子查询纳入,如 第 12 节 所述。

第 13 节 介绍将查询部分约束到特定源图的能力。 第 13 节还展示 SPARQL 为查询定义源图的机制。

第 14 节 引用独立文档 SPARQL 1.1 联邦查询

第 15 节 定义通过排序、切片、投影、限制以及 从解序列中移除重复项来影响查询解的结构。

第 16 节 定义四种 SPARQL 查询类型, 它们以不同形式生成结果。

第 17 节 定义 SPARQL 的可扩展值测试 和表达式框架。它展示可用于约束出现在查询结果中的值,以及计算 查询要返回的新值的函数和运算符。

第 18 节 是对 SPARQL 图模式和解修饰符求值的 形式化定义。

第 19 节 包含 SPARQL 查询和 SPARQL 1.1 更新 语言语法的 规范性定义,该定义以 EBNF 记法表示的文法给出。

1.2 文档约定

1.2.1 命名空间

在本文档中,除非另有说明,示例假定采用以下命名空间前缀定义:

前缀 IRI
rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
rdfs: http://www.w3.org/2000/01/rdf-schema#
xsd: http://www.w3.org/2001/XMLSchema#
fn: http://www.w3.org/2005/xpath-functions#

1.2.2 数据描述

本文档使用 RDF 1.1 Turtle [TURTLE] 数据 格式来显式显示每个三元组。Turtle 允许使用前缀缩写 IRI:

PREFIX dc:   <http://purl.org/dc/elements/1.1/>
PREFIX :     <http://example.org/book/>

:book1  dc:title  "SPARQL Tutorial" .

1.2.3 结果描述

结果集以表格形式说明。

x y z
"Alice" <http://example/a>      

“绑定”是一个二元组(变量RDF 项)。 在此结果集中,有三个变量: xyz(显示为列标题)。每个解 在表格主体中显示为一行。 这里有一个解,其中变量 x 被绑定到 "Alice",变量 y 被绑定到 <http://example/a>,而变量 z 没有绑定到 RDF 项。变量在一个解中并不要求必须被绑定。

1.2.4 术语

SPARQL 语言包含 IRI。 请注意,SPARQL 查询中的所有 IRI 都是绝对的;它们可以包含也可以不包含片段 标识符 [RFC3987] 第 3.1 节。IRI 包含 URI [RFC3986] 和 URL。 SPARQL 语法中的 缩写形式(相对 IRI 和前缀名)会被解析以生成绝对 IRI。

以下术语定义于 RDF 1.2 概念与抽象数据 模型 [RDF12-CONCEPTS],并在 SPARQL 中使用:

空白节点标识符是 SPARQL 和 RDF 具体序列化的一部分。 在本文档中,语法形式“_:abc”用于表示 空白节点标识符abc 的情况,而“_:”是 Turtle 和 SPARQL 中用于引入带标识符的空白节点的语法。

2. 进行简单查询 (资料性)

大多数形式的 SPARQL 查询都包含一组三元组模式,称为基本图 模式。三元组模式类似于 RDF 三元组,但主语、谓语 和宾语中的每一个都可以是变量。当来自 RDF 数据子图的某个 RDF 项 可替换这些变量,并且所得结果与该子图 RDF 图等价时, 基本图模式就匹配该 RDF 数据的一个子图。

2.1 编写简单查询

下面的示例展示一个 SPARQL 查询,用于从给定数据图中查找一本书的标题。 该查询由两部分组成:SELECT 子句标识要出现在查询结果中的 变量,而 WHERE 子句提供要与数据图匹配的 基本图模式。此示例中的基本图模式由一个三元组模式构成,该模式在 宾语位置有一个变量(?title)。

数据:

<http://example.org/book/book1> <http://purl.org/dc/elements/1.1/title> "SPARQL Tutorial" .

查询:

SELECT ?title
WHERE
{
    <http://example.org/book/book1> <http://purl.org/dc/elements/1.1/title> ?title .
}

此查询在上述数据上有一个解:

查询结果:

title
"SPARQL Tutorial"

2.2 多个匹配项

查询的结果是一个解序列, 对应于查询的图模式匹配数据的各种方式。一个查询可以有 零个、一个或多个解。

数据:

PREFIX foaf:  <http://xmlns.com/foaf/0.1/> .

_:a  foaf:name   "Johnny Lee Outlaw" .
_:a  foaf:mbox   <mailto:jlow@example.com> .
_:b  foaf:name   "Peter Goodguy" .
_:b  foaf:mbox   <mailto:peter@example.org> .
_:c  foaf:mbox   <mailto:carol@example.org> .

查询:

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE
{ ?x foaf:name ?name .
  ?x foaf:mbox ?mbox }

查询结果:

name mbox
"Johnny Lee Outlaw" <mailto:jlow@example.com>
"Peter Goodguy" <mailto:peter@example.org>

每个解给出一种方式,在该方式中,被选择的变量可被绑定到 RDF 项, 从而使查询模式与数据匹配。结果集给出所有可能的解。在 上述示例中,数据的以下两个子集提供了两个匹配项。

_:a foaf:name  "Johnny Lee Outlaw" .
_:a foaf:box   <mailto:jlow@example.com> .
_:b foaf:name  "Peter Goodguy" .
_:b foaf:box   <mailto:peter@example.org> .

这是一个基本图模式匹配;查询模式中使用的所有变量 都必须在每个解中被绑定。

2.3 匹配 RDF 字面量

下面的数据包含三个 RDF 字面量:

PREFIX dt:   <http://example.org/datatype#>
PREFIX ns:   <http://example.org/ns#>
PREFIX :     <http://example.org/ns#>
PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>

:x   ns:p     "cat"@en .
:y   ns:p     "42"^^xsd:integer .
:z   ns:p     "abc"^^dt:specialDatatype .

请注意,在 Turtle 中,"cat"@en 是一个 RDF 字面量,其词汇形式为“cat”, 语言标签为“en”;"42"^^xsd:integer 是一个带有 数据类型 http://www.w3.org/2001/XMLSchema#integer 的字面量;而 "abc"^^dt:specialDatatype 是一个带有数据类型 http://example.org/datatype#specialDatatype 的字面量。

该 RDF 数据是第 2.3.1–2.3.3 节中查询示例的数据图。

2.3.1 匹配 带语言标签的字面量

SPARQL 中的语言标签使用 @ 和语言标签表示,如 用于标识语言的标签 [BCP47] 中所定义。

以下查询没有解,因为 "cat""cat"@en 不是同一个 RDF 字面量:

SELECT ?v WHERE { ?v ?p "cat" }
   v    

但下面的查询会找到一个解,其中变量 v 绑定到 :x,因为指定了语言标签且其与给定数据匹配:

SELECT ?v WHERE { ?v ?p "cat"@en }
v
<http://example.org/ns#x>

SPARQL 还支持匹配给定的 基本方向。 与 Turtle 中一样,它写在语言标签之后,例如 @en--ltr。 基本方向被限制为 ltrrtl。 与语言标签不同,它始终为小写。

2.3.2 匹配 带数值类型的字面量

SPARQL 查询中的整数表示数据类型为 xsd:integer 的 RDF 字面量。例如:42 是  "42"^^<http://www.w3.org/2001/XMLSchema#integer> 的缩写形式。

以下查询中的模式有一个解,其中变量 v 绑定到 :y

SELECT ?v WHERE { ?v ?p 42 }
v
<http://example.org/ns#y>

第 4.1.2 节 定义了 SPARQL 中 xsd:floatxsd:double 的缩写形式。

2.3.3 匹配 带任意数据类型的字面量

以下查询有一个解,其中变量 v 绑定到 :z。查询处理器不必对该数据类型值空间中的值有任何理解。 因为词汇形式和数据类型 IRI 都匹配,所以该字面量匹配。

SELECT ?v WHERE { ?v ?p "abc"^^<http://example.org/datatype#specialDatatype> }
v
<http://example.org/ns#z>

2.4 查询结果中的空白节点 标识符

查询结果可以包含空白节点。本文档的示例 结果集中,空白节点写作“_:”后跟一个 空白节点标识符的形式。

空白节点标识符的作用域限定于一个结果集(见“SPARQL 查询结果 XML 格式(第二 版)”和 “SPARQL 1.1 查询结果 JSON 格式”),或者,对于 CONSTRUCT 查询形式而言,限定于结果 图。在一个结果集中使用相同标识符表示同一个空白节点。

数据:
PREFIX foaf:  <http://xmlns.com/foaf/0.1/>

_:a  foaf:name   "Alice" .
_:b  foaf:name   "Bob" .
查询:
PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
SELECT ?x ?name
WHERE  { ?x foaf:name ?name }
x name
_:c "Alice"
_:d "Bob"

上述结果同样可以使用不同的空白节点 标识符给出,因为结果中的空白节点标识符只 表示解中的 RDF 项是否相同或 不同。

x name
_:r "Alice"
_:s "Bob"

这两个结果包含相同信息:用于 匹配查询的空白节点在两个解中是不同的。结果集中的空白节点标识符 _:a 与 数据语法中使用的空白节点标识符之间不需要 存在任何关系。

应用程序编写者不应期望查询中的空白节点标识符 指向数据中的某个特定空白节点。

2.5 使用表达式创建值

SPARQL 1.2 允许从复杂表达式创建值。下面的查询展示 CONCAT 函数如何用于连接 FOAF 数据中的名字和 姓氏,然后使用 SELECT 子句中的表达式来赋值,也可以使用 BIND 形式赋值。

数据:
PREFIX foaf:  <http://xmlns.com/foaf/0.1/>
            
_:a  foaf:givenName   "John" .
_:a  foaf:surname  "Doe" .
查询:
PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
SELECT ( CONCAT(?G, " ", ?S) AS ?name )
WHERE  { ?P foaf:givenName ?G ; foaf:surname ?S }
查询:
PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE  { 
    ?P foaf:givenName ?G ; 
       foaf:surname ?S 
    BIND(CONCAT(?G, " ", ?S) AS ?name)
}
name
"John Doe"

2.6 构建 RDF 图

SPARQL 有若干查询形式SELECT 查询 形式返回变量绑定。CONSTRUCT 查询形式返回 RDF 图。 该图基于一个模板构建,该模板用于根据查询图模式匹配的 结果生成 RDF 三元组。

数据:

PREFIX org:    <http://example.com/ns#>

_:a  org:employeeName   "Alice" .
_:a  org:employeeId     12345 .

_:b  org:employeeName   "Bob" .
_:b  org:employeeId     67890 .

查询:

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
PREFIX org:    <http://example.com/ns#>

CONSTRUCT { ?x foaf:name ?name }
WHERE  { ?x org:employeeName ?name }

结果:

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
                
_:x foaf:name "Alice" .
_:y foaf:name "Bob" .

它可以被序列化为 RDF/XML

<rdf:RDF
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:foaf="http://xmlns.com/foaf/0.1/" >

  <rdf:Description>
    <foaf:name>Alice</foaf:name>
  </rdf:Description>
  <rdf:Description>
    <foaf:name>Bob</foaf:name>
  </rdf:Description>
</rdf:RDF>

3. RDF 项约束(资料性)

图模式匹配会产生一个解序列,其中每个解都有一组 变量到 RDF 项的绑定。SPARQL FILTER 将解限制为 过滤表达式求值为 TRUE 的那些解。

本节提供对 SPARQL FILTER 的非正式介绍;它们的 语义定义在“表达式与值测试”一节中, 其中有一个完整的函数库。本节中的示例 共享一个输入图:

数据:
PREFIX dc:   <http://purl.org/dc/elements/1.1/>
PREFIX :     <http://example.org/book/>
PREFIX ns:   <http://example.org/ns#>

:book1  dc:title  "SPARQL Tutorial" .
:book1  ns:price  42 .
:book2  dc:title  "The Semantic Web" .
:book2  ns:price  23 .

3.1 限制 字符串的值

SPARQL FILTER 函数,如 regex,可以 测试 RDF 字面量。regex 只匹配字符串 字面量regex 可以通过使用 str 函数 来匹配其他字面量的词汇形式。

查询:

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
SELECT  ?title
WHERE   { 
    ?x dc:title ?title
    FILTER regex(?title, "^SPARQL") 
}

查询结果:

title
"SPARQL Tutorial"

可使用“i” 标志使正则表达式匹配不区分大小写。

查询:

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
SELECT  ?title
WHERE   { 
    ?x dc:title ?title
    FILTER regex(?title, "web", "i" ) 
}

查询结果:

title
"The Semantic Web"

正则表达式语言由 XQuery 和 XPath 函数与运算符定义,并基于 XML Schema 正则表达式

3.2 限制数值

SPARQL FILTER 可以对算术表达式进行限制。

查询:

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>

SELECT  ?title ?price
WHERE   {
    ?x ns:price ?price .
    FILTER (?price < 30.5)
    ?x dc:title ?title . 
}

查询结果:

title price
"The Semantic Web" 23

通过约束 price 变量,只有 :book2 匹配该查询, 因为只有 :book2 的价格小于 30.5,符合过滤 条件要求。

3.3 其他项约束

数值 类型外,SPARQL 还支持 xsd:stringxsd:booleanxsd:dateTime 类型(见操作数数据类型)。运算符映射一节 描述运算符,函数定义一节描述 可应用于 RDF 项的函数。

4. SPARQL 语法

本节涵盖 SPARQL 用于 RDF 项三元组模式的语法。 完整文法见第 19 节

4.1 RDF 项语法

4.1.1 IRI 的语法

iri 产生式表示 IRI 集合 [RFC3987];IRI 是 URI [RFC3986] 的泛化,并且与 URI 和 URL 完全兼容。PrefixedName 产生式表示前缀名。前缀名到 IRI 的映射如下所述。IRI 引用(相对或 绝对 IRI)由 IRIREF 产生式表示,其中 “<”和“>”分隔符不构成 IRI 引用的一部分。相对 IRI 匹配 [RFC3987] 中第 2.2 节 “IRI 引用和 IRI 的 ABNF”里的 irelative-ref 引用,并按下文所述解析 为 IRI。

4.1.1.1 前缀名

PREFIX 关键字将一个前缀标签与一个 IRI 关联。前缀名 是由冒号“:”分隔的前缀标签和局部部分。前缀 名通过将与前缀关联的 IRI 和局部部分连接起来映射为 IRI。 前缀标签或局部部分可以为空。 请注意,SPARQL 局部名允许以数字开头,而 XML 局部名不允许。 SPARQL 局部名还允许通过反斜杠 字符转义使用 IRI 中允许的非字母数字 字符(例如 ns:id\=123)。SPARQL 局部 名CURIE 有更多语法限制。

4.1.1.2 相对 IRI

相对 IRI 按照 统一资源标识符(URI):通用 语法 [RFC3986] 与基 IRI 组合,只使用第 5.2 节中的基本算法。不执行基于语法的规范化或基于方案的 规范化(见 [RFC3986] 第 6.2.2 和 6.2.3 节)。 IRI 引用中额外允许的字符按未保留字符在 URI 引用中的处理方式处理, 如 国际化资源标识符 (IRI) [RFC3987] 第 6.5 节所述。

BASE 关键字定义用于根据 [RFC3986] 第 5.1.1 节“嵌入内容中的基 URI”解析相对 IRI 的基 IRI。第 5.1.2 节“来自 封装实体的基 URI”定义基 IRI 如何来自封装 文档,例如带有 xml:base 指令的 SOAP 信封,或带有 Content-Location 标头的 mime 多部分文档。 第 5.1.3 节“来自检索 URI 的基 URI”中标识的“检索 URI”,是获取特定 SPARQL 查询的 URL。如果 以上都未指定基 URI,则使用默认基 URI(第 5.1.4 节“默认 基 URI”)。

以下片段是写出同一 IRI 的几种不同方式:

<http://example.org/book/book1>
BASE <http://example.org/book/>
<book1>
PREFIX book: <http://example.org/book/>
book:book1

4.1.2 字面量的语法

字面量的一般语法是一个字符串(用双引号 "..." 或单引号 '...' 括起),并带有可选的语言 标签(由 @ 引入),或可选的数据类型 IRI 或前缀名(由 ^^ 引入)。

为方便起见,整数可以直接书写(不加引号,也不显式写出 数据类型 IRI),并解释为数据类型为 xsd:integer 的字面量;数字中有“.”但没有 指数的十进制数解释为 xsd:decimal;带指数的数字 解释为 xsd:doublexsd:boolean 类型的值也可以 写作 truefalse

为了便于书写本身包含引号或较长且包含换行符的 字面量值,SPARQL 提供了额外的引号结构,在 这种结构中字面量用三个单引号或双引号括起。

SPARQL 中的字面量语法示例包括:

  • "chat"
  • 带语言标签“fr”的 'chat'@fr
  • "xyz"^^<http://example.org/ns/userDatatype>
  • "abc"^^appNS:appDataType
  • '''The librarian said, "Perhaps you would enjoy 'War and Peace'."'''
  • 1,等同于 "1"^^xsd:integer
  • 1.3,等同于 "1.3"^^xsd:decimal
  • 1.300,等同于 "1.300"^^xsd:decimal
  • 1.0e6,等同于 "1.0e6"^^xsd:double
  • true,等同于 "true"^^xsd:boolean
  • false,等同于 "false"^^xsd:boolean

匹配以下任一产生式的标记 INTEGERDECIMALDOUBLEBooleanLiteral 等同于一个字面量, 其词汇值为该标记,数据类型为相应的数据类型 (xsd:integerxsd:decimalxsd:doublexsd:boolean)。

4.1.3 查询变量的语法

查询变量由“?”或“$”标记;“?”或“$”不是 变量名的一部分。在查询中,$abc?abc 标识同一个 变量。变量的可能名称SPARQL 文法中给出。

4.1.4 空白节点的语法

图模式中的 空白节点 充当变量,而不是对被查询数据中特定空白 节点的引用。空白节点由 标识符形式(例如“_:abc”)或 使用“[]”或“[...]”的缩写形式表示。

空白节点标识符写作“_:abc”,表示 标识符为“abc”的空白节点。同一个空白节点 标识符不能在同一查询中的两个不同基本图模式中使用。

只在查询语法中的一个位置使用的空白节点可以用 [] 表示。将使用一个唯一的空白节点来 形成三元组模式。

[:p :v] 结构可用于创建三元组 模式,其中唯一空白节点作为所含 谓词-对象对的主语。

以下两种形式

[ :p "v" ] .
[] :p "v" .

分配一个唯一空白节点(此处用 “_:b57”说明),并且二者等同于写作:

_:b57 :p "v" .

分配的空白节点可用作 进一步三元组模式的主语或宾语。例如,作为主语:

[ :p "v" ] :q "w" .

这等同于以下两个三元组:

_:b57 :p "v" .
_:b57 :q "w" .

作为宾语时:

:x :q [ :p "v" ] .

这等同于以下两个三元组:

:x  :q _:b57 .
_:b57 :p "v" .

缩写空白节点语法可以与用于共同主语共同谓语的其他 缩写结合使用。

[ foaf:name  ?name ;
  foaf:mbox  <mailto:alice@example.org> ]

这等同于使用空白节点标识符来书写以下 基本图模式。

_:b18  foaf:name  ?name .
_:b18  foaf:mbox  <mailto:alice@example.org> .

4.2 三元组模式的语法

三元组模式写作主语、谓语和 宾语;某些常见三元组模式结构有缩写写法。

以下示例表达同一个查询:

PREFIX  dc: <http://purl.org/dc/elements/1.1/>
SELECT  ?title
WHERE   { <http://example.org/book/book1> dc:title ?title }
PREFIX  dc: <http://purl.org/dc/elements/1.1/>
PREFIX  : <http://example.org/book/>

SELECT  $title
WHERE   { :book1  dc:title  $title }
BASE    <http://example.org/book/>
PREFIX  dc: <http://purl.org/dc/elements/1.1/>

SELECT  $title
WHERE   { <book1>  dc:title  ?title }

4.2.1 谓词-对象列表

具有共同主语的三元组模式可以这样书写:主语只写 一次,并通过使用“;” 记法用于多个三元组模式。

?x  foaf:name  ?name ;
foaf:mbox  ?mbox .

这等同于写出以下三元组模式:

?x  foaf:name  ?name .
?x  foaf:mbox  ?mbox .

4.2.2 对象列表

如果三元组模式同时共享主语和谓语,则对象可以用 “,”分隔。

?x foaf:nick  "Alice" , "Alice_" .

等同于写出以下三元组模式:

?x  foaf:nick  "Alice" .
?x  foaf:nick  "Alice_" .

对象列表可以与谓词-对象列表结合使用:

?x  foaf:name ?name ; foaf:nick  "Alice" , "Alice_" .

等价于:

?x  foaf:name  ?name .
?x  foaf:nick  "Alice" .
?x  foaf:nick  "Alice_" .

4.2.3 RDF 集合

RDF 集合可以用语法“(element1 element2 ...)”写入三元组 模式中。形式“()”是 IRI http://www.w3.org/1999/02/22-rdf-syntax-ns#nil 的另一种写法。 当与集合元素一起使用时,例如 (1 ?x 3 4),会为集合分配带 空白节点的三元组模式。集合头部的空白节点 可以在其他三元组模式中用作主语或宾语。由 集合语法分配的空白节点不会出现在查询中的其他地方。

(1 ?x 3 4) :p "w" .

是以下内容的语法糖(注意 b0b1b2b3 不会出现在查询的任何其他地方):

_:b0  rdf:first  1 ;
      rdf:rest   _:b1 .
_:b1  rdf:first  ?x ;
      rdf:rest   _:b2 .
_:b2  rdf:first  3 ;
      rdf:rest   _:b3 .
_:b3  rdf:first  4 ;
      rdf:rest   rdf:nil .
_:b0  :p         "w" .

RDF 集合可以嵌套,并且可以涉及其他语法形式:

(1 [:p :q] ( 2 ) ) .

是以下内容的语法糖:

_:b0  rdf:first  1 ;
      rdf:rest   _:b1 .
_:b1  rdf:first  _:b2 .
_:b2  :p         :q .
_:b1  rdf:rest   _:b3 .
_:b3  rdf:first  _:b4 .
_:b4  rdf:first  2 ;
      rdf:rest   rdf:nil .
_:b3  rdf:rest   rdf:nil .

4.2.4 rdf:type

关键字“a”可以在三元组模式中用作谓语,并且是 IRI  http://www.w3.org/1999/02/22-rdf-syntax-ns#type 的另一种写法。 此关键字区分大小写。

?x  a  :Class1 .
[ a :appClass ] :p "v" .

是以下内容的语法糖:

?x    rdf:type  :Class1 .
_:b0  rdf:type  :appClass .
_:b0  :p        "v" .

4.3 版本声明

为应对 SPARQL 的语言演化, 可以使用 VERSION 指令。 当编写使用新特性的 SPARQL 查询时,例如 三元组项三元组项上的函数, 作者可以通过包含此 指令来声明使用新的语法形式, 后跟表示处理所包含特性所需版本的版本标签。

版本标签在下一节中定义。 处理器可以将无法识别的标签视为错误或警告。

VERSION "1.2"
PREFIX : <http://example/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?s ?date {
    ?s ?p ?o .
    BIND( <<( ?s ?p ?o )>> AS ?tt )
    :myreifier rdf:reifies ?tt .
    :myreifier :tripleAdded ?date .
}

SPARQL 1.2 协议还提供了一个 版本声明,该声明使用 媒体类型version 参数。 如果没有 VERSION 指令,则会考虑这一点。

4.3.1 版本标签

SPARQL 版本标签是一个字符串,用于 标识 SPARQL 查询的语法和语义一致性。

尽管 SPARQL 中的版本标签字符串与 RDF 定义的版本标签相同, 但它们的含义不同。具体而言,SPARQL 版本标签指的是 SPARQL 语法和语义,而 RDF 版本标签指的是 RDF 语法 和语义。

SPARQL 版本标签
版本标签 语法 语义
"1.2" SPARQL 1.2 查询或更新语法 SPARQL 1.2 查询 语言SPARQL 1.2 更新
"1.2-basic" SPARQL 1.2 查询或更新语法,不含三元组项,也不含 主语或宾语位置上有三元组模式的三元组模式 SPARQL 1.2 查询 语言SPARQL 1.2 更新
"1.1" SPARQL 1.1 查询或更新语法,但允许使用版本指令 SPARQL 1.1 查询 语言SPARQL 1.1 更新

如果一个查询符合版本“1.1”,它也符合版本“1.2-basic”; 如果一个查询符合版本“1.2-basic”,它也符合版本“1.2”。

虽然“1.1”是可接受的版本标签, 但不鼓励在 VERSION 指令中使用它, 因为这会不必要地导致 SPARQL 1.1 解析器失败。

5. 图模式

SPARQL 围绕图模式匹配构建。可以通过以各种方式 组合较小模式来形成更复杂的图模式:

在本节中,我们描述通过合取来组合模式的两种形式:基本图 模式,它组合三元组模式;以及组图模式,它组合所有其他 图模式。

查询中最外层的图模式称为查询模式。它在语法上 由 GroupGraphPattern 标识,如下所示

[17]   WhereClause   ::=   'WHERE'? GroupGraphPattern

5.1 基本图模式

基本图模式是三元组模式的集合。SPARQL 图模式匹配是根据 组合基本图模式匹配结果来定义的。

一组三元组模式序列,加上可选过滤器,构成一个基本图 模式。任何其他图模式都会终止一个基本图模式。

5.1.1 空白节点标识符

使用 _:abc 形式的空白节点时,空白节点的标识符 作用域限定于基本图模式。一个 空白节点标识符 在任何查询中只能用于一个基本图模式。

5.1.2 扩展 基本图模式匹配

SPARQL 使用子图匹配对基本图模式求值,这一定义适用于 简单蕴涵。在满足下文所述的 某些条件时,SPARQL 可以扩展到其他形式的蕴涵。 文档 SPARQL 1.1 蕴涵制度 描述了若干具体的蕴涵制度。

5.2 组图模式

在 SPARQL 查询字符串中,组图模式用花括号分隔:{}。 例如,此查询的查询模式是由一个基本图 模式组成的组图模式。

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE  {
    ?x foaf:name ?name .
    ?x foaf:mbox ?mbox .
}
如果将三元组模式分组为两个基本图模式,查询会得到相同的解。 例如,下面的查询结构不同,但会产生与前一个查询相同的解:
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE  { 
   { ?x foaf:name ?name . }
   { ?x foaf:mbox ?mbox . }
}

5.2.1 空组模式

组模式:

{ }

匹配任意图(包括空图),并产生一个不绑定任何 变量的解。例如:

SELECT ?x
WHERE {}

会匹配并产生一个解,其中变量 x 未绑定。

5.2.2 过滤器的作用域

由关键字 FILTER 表达的约束,是对 该过滤器所在整个组中的解的限制。以下模式都有 相同的解:

{  ?x foaf:name ?name .
   ?x foaf:mbox ?mbox .
   FILTER regex(?name, "Smith")
}
{  FILTER regex(?name, "Smith")
   ?x foaf:name ?name .
   ?x foaf:mbox ?mbox .
}
{  ?x foaf:name ?name .
   FILTER regex(?name, "Smith")
   ?x foaf:mbox ?mbox .
}

5.2.3 组图模式 示例

{ ?x foaf:name ?name .
  ?x foaf:mbox ?mbox .
}

是由一个基本图模式组成的组,而该基本图模式由两个 三元组模式组成。

{
  ?x foaf:name ?name . FILTER regex(?name, "Smith")
  ?x foaf:mbox ?mbox .
}

是由一个基本图模式和一个过滤器组成的组,而该基本图模式 由两个三元组模式组成;过滤器不会将基本图模式拆分为两个 基本图模式。

{
  ?x foaf:name ?name .
  {}
  ?x foaf:mbox ?mbox .
}

是由三个元素组成的组:一个由一个三元组模式组成的基本图模式、一个空 组,以及另一个由一个三元组模式组成的基本图模式。

6. 包含可选值

基本图模式允许应用进行查询,其中整个查询模式必须 匹配才会有解。对于只包含组图 模式且至少有一个基本图模式的查询的每个解,每个变量都绑定到解中的一个 RDF 项。 然而,不能假定所有 RDF 图中都有规则、完整的结构。能够编写这样的查询很有用: 当信息可用时允许把信息加入解中,但不会因为查询模式的某一部分 不匹配而拒绝该解。可选匹配提供了这一功能:如果可选部分不匹配, 它不会创建绑定,但也不会消除该解。

6.1 可选模式匹配

图模式的可选部分可以在语法上通过将 OPTIONAL 关键字应用于图模式来指定:

pattern OPTIONAL { pattern }

语法形式:

{ OPTIONAL { pattern } }

等价于:

{ { } OPTIONAL { pattern } }

OPTIONAL 关键字是左结合的:

pattern OPTIONAL { pattern } OPTIONAL { pattern }

与以下形式相同:

{ pattern OPTIONAL { pattern } } OPTIONAL { pattern }

在可选匹配中,要么可选图模式匹配某个图,从而 为一个或多个解定义并添加绑定;要么它使解保持不变, 不添加任何额外绑定。

数据:

PREFIX foaf:       <http://xmlns.com/foaf/0.1/>
PREFIX rdf:        <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

_:a  rdf:type        foaf:Person .
_:a  foaf:name       "Alice" .
_:a  foaf:mbox       <mailto:alice@example.com> .
_:a  foaf:mbox       <mailto:alice@work.example> .

_:b  rdf:type        foaf:Person .
_:b  foaf:name       "Bob" .
查询:
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE  {
    ?x foaf:name  ?name .
    OPTIONAL { ?x  foaf:mbox  ?mbox }
}

对于上述数据,查询结果为:

name mbox
"Alice" <mailto:alice@example.com>
"Alice" <mailto:alice@work.example>
"Bob"

在名称为 "Bob" 的解中,没有 mbox 的值。

此查询查找数据中人员的姓名。如果存在一个谓词为 mbox 且主语相同的三元组,则解也会包含该三元组的宾语。 在此示例中,查询的可选匹配部分只给出一个三元组模式, 但一般而言,可选部分可以是任意图模式。整个可选 图模式必须匹配,才会影响查询解。

6.2 可选模式匹配中的 约束

约束可以在可选图模式中给出。例如:

PREFIX dc:   <http://purl.org/dc/elements/1.1/>
PREFIX :     <http://example.org/book/>
PREFIX ns:   <http://example.org/ns#>

:book1  dc:title  "SPARQL Tutorial" .
:book1  ns:price  42 .
:book2  dc:title  "The Semantic Web" .
:book2  ns:price  23 .
PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>
SELECT  ?title ?price
WHERE   { 
    ?x dc:title ?title .
    OPTIONAL { ?x ns:price ?price . FILTER (?price < 30) }
}
title price
"SPARQL Tutorial"
"The Semantic Web" 23

标题为“SPARQL Tutorial”的书没有出现价格,因为可选图 模式没有产生涉及变量“price”的解。

6.3 多个可选图 模式

图模式是递归定义的。一个图模式可以有零个或多个可选 图模式,查询模式的任何部分也都可以有可选部分。在此示例中, 有两个可选图模式。

数据:
PREFIX foaf:       <http://xmlns.com/foaf/0.1/>

_:a  foaf:name       "Alice" .
_:a  foaf:homepage   <http://work.example.org/alice/> .

_:b  foaf:name       "Bob" .
_:b  foaf:mbox       <mailto:bob@work.example> .
查询:
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox ?hpage
WHERE  {
    ?x foaf:name  ?name .
    OPTIONAL { ?x foaf:mbox ?mbox } .
    OPTIONAL { ?x foaf:homepage ?hpage }
}

查询结果:

name mbox hpage
"Alice" <http://work.example.org/alice/>
"Bob" <mailto:bob@work.example>

7. 匹配替代项

SPARQL 提供了一种组合图模式的手段,使得若干替代图 模式中的一个可以匹配。如果多个替代项匹配,则会找到所有可能的模式 解。

模式替代项在语法上用 UNION 关键字指定。

数据:
PREFIX dc10:  <http://purl.org/dc/elements/1.0/>
PREFIX dc11:  <http://purl.org/dc/elements/1.1/>

_:a  dc10:title     "SPARQL Query Language Tutorial" .
_:a  dc10:creator   "Alice" .

_:b  dc11:title     "SPARQL Protocol Tutorial" .
_:b  dc11:creator   "Bob" .

_:c  dc10:title     "SPARQL" .
_:c  dc11:title     "SPARQL (updated)" .
查询:
PREFIX dc10:  <http://purl.org/dc/elements/1.0/>
PREFIX dc11:  <http://purl.org/dc/elements/1.1/>

SELECT ?title
WHERE  { { ?book dc10:title  ?title } UNION { ?book dc11:title  ?title } }

查询结果:

title
"SPARQL Protocol Tutorial"
"SPARQL"
"SPARQL (updated)"
"SPARQL Query Language Tutorial"

此查询查找数据中书籍的标题,无论该标题是使用 Dublin Core 版本 1.0 还是版本 1.1 的属性记录的。若要准确确定信息是如何记录的,查询可以为 两个替代项使用不同变量:

PREFIX dc10:  <http://purl.org/dc/elements/1.0/>
PREFIX dc11:  <http://purl.org/dc/elements/1.1/>

SELECT ?x ?y
WHERE  { { ?book dc10:title ?x } UNION { ?book dc11:title  ?y } }
x y
"SPARQL (updated)"
"SPARQL Protocol Tutorial"
"SPARQL"
"SPARQL Query Language Tutorial"

这会返回这样的结果:来自 UNION 左分支的解中变量 x 被绑定,而来自右分支的解中变量 y 被绑定。 如果 UNION 模式的任何一部分都没有匹配,则图 模式不会匹配。

UNION 模式组合图模式;每种替代可能性都可以 包含多个三元组模式:

PREFIX dc10:  <http://purl.org/dc/elements/1.0/>
PREFIX dc11:  <http://purl.org/dc/elements/1.1/>

SELECT ?title ?author
WHERE {
    { ?book dc10:title ?title .  ?book dc10:creator ?author }
      UNION
    { ?book dc11:title ?title .  ?book dc11:creator ?author }
}
title author
"SPARQL Query Language Tutorial" "Alice"
"SPARQL Protocol Tutorial" "Bob"

此查询只有在一本书同时具有来自同一版本 Dublin Core 的标题谓词和创建者谓词时才会匹配该书。

8. 否定

SPARQL 查询语言包含两种否定方式:一种基于在被过滤的查询 解的上下文中,某个图模式是否匹配来过滤结果;另一种基于移除与另一个模式相关的解。

8.1 使用图模式进行过滤

查询解的过滤在 FILTER 表达式中使用 NOT EXISTSEXISTS 完成。请注意,过滤器作用域规则 适用于该过滤器所在的整个组

8.1.1 测试模式 是否不存在

NOT EXISTS 过滤表达式测试在过滤器所在组图模式中的变量值 给定时,某个图模式是否不匹配数据集。它不会生成任何额外绑定。

数据:

PREFIX  :       <http://example/>
PREFIX  rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX  foaf:   <http://xmlns.com/foaf/0.1/>

:alice  rdf:type   foaf:Person .
:alice  foaf:name  "Alice" .
:bob    rdf:type   foaf:Person .

查询:

PREFIX  rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
PREFIX  foaf:   <http://xmlns.com/foaf/0.1/> 

SELECT ?person
WHERE 
{
    ?person rdf:type  foaf:Person .
    FILTER NOT EXISTS { ?person foaf:name ?name }
}

查询结果:

person
<http://example/bob>

8.1.2 测试模式 是否存在

还提供了过滤表达式 EXISTS。它测试是否能在数据中找到该模式; 它不会生成任何额外绑定。

查询:

PREFIX  rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
PREFIX  foaf:   <http://xmlns.com/foaf/0.1/> 

SELECT ?person
WHERE {
    ?person rdf:type  foaf:Person .
    FILTER EXISTS { ?person foaf:name ?name }
}

查询结果:

person
<http://example/alice>

8.2 移除可能的解

SPARQL 提供的另一种否定方式是 MINUS,它对两个 参数求值,然后计算左侧中与右侧解不兼容的解。

数据:
PREFIX :       <http://example/>
PREFIX foaf:   <http://xmlns.com/foaf/0.1/>

:alice  foaf:givenName "Alice" ;
        foaf:familyName "Smith" .

:bob    foaf:givenName "Bob" ;
        foaf:familyName "Jones" .

:carol  foaf:givenName "Carol" ;
        foaf:familyName "Smith" .
查询:
PREFIX :       <http://example/>
PREFIX foaf:   <http://xmlns.com/foaf/0.1/>

SELECT DISTINCT ?s
WHERE {
    ?s ?p ?o .
    MINUS {
        ?s foaf:givenName "Bob" .
    }
}

结果:

s
<http://example/carol>
<http://example/alice>

8.3 NOT EXISTS 与 MINUS 之间的关系和差异

NOT EXISTSMINUS 表示对 否定的两种理解方式:一种基于在已由查询模式确定的绑定 给定时测试某个模式是否存在于数据中,另一种基于两个模式的 求值来移除匹配项。在某些情况下,它们可能产生不同答案。

8.3.1 示例:变量的共享

PREFIX : <http://example/>
:a :b :c .
SELECT * { 
    ?s ?p ?o
    FILTER NOT EXISTS { ?x ?y ?z }
}

求值为一个没有解的结果集,因为 { ?x ?y ?z } 在任何给定 ?s ?p ?o 的情况下都会匹配,所以 NOT EXISTS { ?x ?y ?z } 会消除所有解。

s p o

而使用 MINUS 时,第一部分 (?s ?p ?o)和第二部分(?x ?y ?z)之间没有共享变量, 因此不会消除任何绑定。

SELECT * { 
    ?s ?p ?o 
    MINUS 
    { ?x ?y ?z }
}

结果:

s p o
<http://example/a> <http://example/b> <http://example/c>

8.3.2 示例:固定模式

另一种情况是示例中存在一个具体模式(没有变量):

PREFIX : <http://example/>
SELECT * {  
    ?s ?p ?o 
    FILTER NOT EXISTS { :a :b :c }
}

求值为一个没有查询解的结果集:

结果:
s p o

PREFIX : <http://example/>
SELECT * 
{ 
    ?s ?p ?o 
    MINUS { :a :b :c }
}

求值为包含一个查询解的结果集:

结果:

s p o
<http://example/a> <http://example/b> <http://example/c>

因为没有绑定匹配,所以没有解被消除。

8.3.3 示例:内部 FILTER

也会出现差异,因为在过滤器中,来自组的变量 处于作用域内。 在此示例中,NOT EXISTS 内部的 FILTER 可以访问当前考虑的解中 ?n 的值。

PREFIX : <http://example.com/>
:a :p 1 .
:a :q 1 .
:a :q 2 .

:b :p 3.0 .
:b :q 4.0 .
:b :q 5.0 .

使用 FILTER NOT EXISTS 时,测试针对 ?x :p ?n 的每个可能解进行:

PREFIX : <http://example.com/>
SELECT * WHERE {
    ?x :p ?n
    FILTER NOT EXISTS {
        ?x :q ?m .
        FILTER(?n = ?m)
    }
}
x n
<http://example.com/b> 3.0

而使用 MINUS 时,模式内部的 FILTER 没有 ?n 的值,因此它始终未绑定:

PREFIX : <http://example/>
SELECT * WHERE {
    ?x :p ?n
    MINUS {
        ?x :q ?m .
        FILTER(?n = ?m)
    }
}
x n
<http://example.com/b> 3.0
<http://example.com/a> 1

9. 属性路径

属性路径是图中两个图节点之间可能的路径。一个平凡情况 是长度恰好为 1 的属性路径,即一个三元组模式。路径的两端可以是 RDF 项或变量。变量不能用作路径本身的一部分,只能用于 两端。

属性路径允许对某些 SPARQL 基本图模式使用更简洁的表达, 并且还增加了通过任意长度 路径匹配两个资源连通性的能力。

9.1 属性路径语法

在下面的描述中,iri 要么是完整写出的 IRI 或用前缀名缩写的 IRI,要么是关键字 aelt 是一个路径元素,它本身可以由路径结构组成。

语法形式 属性路径表达式名称 匹配项
iri PredicatePath 一个 IRI。长度为一的路径。
^elt InversePath 反向路径(从宾语到主语)。
elt1 / elt2 SequencePath elt1 后跟 elt2 的序列路径。
elt1 | elt2 AlternativePath elt1elt2 的替代路径(会尝试所有 可能性)。
elt* ZeroOrMorePath 通过零次或多次匹配 elt 来连接路径主语和宾语的路径。
elt+ OneOrMorePath 通过一次或多次匹配 elt 来连接路径主语和宾语的路径。
elt? ZeroOrOnePath 通过零次或一次匹配 elt 来连接路径主语和宾语的路径。
!iri or !(iri1| ...|irin) NegatedPropertySet 否定属性集。不是 irii 之一的 IRI。 !iri!(iri) 的缩写。
!^iri or !(^iri1| ...|^irin) NegatedPropertySet 否定属性集,其中被排除的匹配基于反向路径。
也就是说,不是作为反向路径的 iri1...irin 之一。 !^iri!(^iri) 的缩写。
!(iri1| ...|irij|^irij+1| ...|^irin) NegatedPropertySet 否定属性集中正向属性与反向属性的组合。
(elt)   组路径 elt,括号控制优先级。

否定属性集中 IRI 和反向 IRI 的顺序并不重要,它们 可以以混合顺序出现。

语法形式的优先级从高到低如下:

组内优先级从左到右。

9.2 示例

替代项:匹配一种或两种可能性

{ :book1 dc:title|rdfs:label ?displayString }

也可以写作:

{ 
   :book1 <http://purl.org/dc/elements/1.1/title> | <http://www.w3.org/2000/01/rdf-schema#label> ?displayString
}

序列:查找 Alice 认识的任何人的姓名。

{
    ?x foaf:mbox <mailto:alice@example> .
    ?x foaf:knows/foaf:name ?name .
}

序列:查找距离 2 条“foaf:knows”链接的人的姓名。

{ 
    ?x foaf:mbox <mailto:alice@example> .
    ?x foaf:knows/foaf:knows/foaf:name ?name .
}

这与以下 SPARQL 查询相同:

SELECT ?x ?name {
    ?x  foaf:mbox <mailto:alice@example> .
    ?x  foaf:knows [ foaf:knows [ foaf:name ?name ]]. 
}

或者,使用显式变量:

SELECT ?x ?name {
    ?x  foaf:mbox <mailto:alice@example> .
    ?x  foaf:knows ?a1 .
    ?a1 foaf:knows ?a2 .
    ?a2 foaf:name ?name .
}

过滤重复项:因为 Alice 认识的人很可能认识 Alice,所以上面的示例 可能包含 Alice 本人。可使用以下方式避免这种情况:

{ ?x foaf:mbox <mailto:alice@example> .
  ?x foaf:knows/foaf:knows ?y .
  FILTER ( ?x != ?y )
  ?y foaf:name ?name 
}

反向属性路径:这两个是同一个查询;第二个只是反转 属性方向,从而交换主语和宾语的角色。

{ ?x foaf:mbox <mailto:alice@example> }
{ <mailto:alice@example> ^foaf:mbox ?x }

反向路径序列:查找所有认识 ?x 所认识的某人的人。

{
  ?x foaf:knows/^foaf:knows ?y .  
  FILTER(?x != ?y)
}

这等价于(?gen1 是系统生成的变量):

{
  ?x foaf:knows ?gen1 .
  ?y foaf:knows ?gen1 .  
  FILTER(?x != ?y)
}

任意长度匹配:查找所有可从 Alice 通过 foaf:knows 到达的人的姓名:

{
  ?x foaf:mbox <mailto:alice@example> .
  ?x foaf:knows+/foaf:name ?name .
}

任意长度路径中的替代项

{ ?ancestor (ex:motherOf|ex:fatherOf)+ <#me> }

任意长度路径匹配:某些形式的有限推理也是可能的。 例如,对于 RDFS,资源的所有类型和超类型:

{ <http://example/thing> rdf:type/rdfs:subClassOf* ?type }

所有资源及其所有推断类型:

{ ?x rdf:type/rdfs:subClassOf* ?type }

子属性

{ ?x ?p ?v . ?p rdfs:subPropertyOf* :property }

否定属性路径:查找已连接但不是通过 rdf:type 连接的节点(任一方向):

{ ?x !(rdf:type|^rdf:type) ?y }

RDF 集合中的元素

{ :list rdf:rest*/rdf:first ?element }

注:此路径表达式不保证结果的顺序。

9.3 属性路径与 等价模式

SPARQL 属性路径将 RDF 三元组视为一个有向的、可能有环的、带 命名边的图。属性路径表达式的求值可能导致重复项,因为 等价模式中引入的任何变量都不是结果的一部分,也未在其他地方 使用。它们会被结果隐式投影到仅查询中给出的变量而隐藏。

例如,基于以下数据:

PREFIX :       <http://example/>

:order  :item :z1 .
:order  :item :z2 .

:z1 :name "Small" .
:z1 :price 5 .

:z2 :name "Large" .
:z2 :price 5 .

查询:

PREFIX :   <http://example/>
SELECT * 
{  ?s :item/:price ?x . }

结果:

s x
<http://example/order> 5
<http://example/order> 5

而如果将查询写出以包含中间变量 (?_a),结果中就没有重复行:

PREFIX :   <http://example/>
SELECT * 
{  ?s :item ?_a .
   ?_a :price ?x .
}

结果:

s _a x
<http://example/order> <http://example/z1> 5
<http://example/order> <http://example/z2> 5

当查询还涉及聚合操作时,与图模式的等价性尤其重要。 可以用以下方式求得订单的总成本

PREFIX :   <http://example/>
SELECT (sum(?x) AS ?total) { 
    :order :item/:price ?x
}
total
10

9.4 任意长度路径匹配

可以使用“零次或多次”属性路径运算符 * 和“一次或多次” 属性路径运算符 +,找到主语和宾语之间通过任意长度属性路径形成的 连通性。还有一个“零次或一次”连通性属性 路径运算符 ?

这些运算符都会使用属性路径表达式,按该运算符所限制的次数 尝试使用路径步骤在主语和宾语之间找到连接。

例如,可以用以下方式找到资源的所有可能类型,包括资源的超类型:

PREFIX  rdfs:   <http://www.w3.org/2000/01/rdf-schema#> . 
PREFIX  rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?x ?type
{ 
    ?x rdf:type/rdfs:subClassOf* ?type
}

类似地,查找所有通过 foaf:knows 关系与 :x 相连的人,

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX :     <http://example/>
SELECT ?person
{ 
    :x foaf:knows+ ?person
}

这种连通性匹配不会引入重复项(它不会包含 该连接可形成方式数量的任何计数),即使重复路径本身 原本会导致重复项。

被匹配的图可以包含环。连通性匹配的定义保证 匹配环不会导致未定义或无限结果。

10. 赋值

表达式的值可以通过把一个新变量绑定到 该表达式的值而加入解映射,该值是一个 RDF 项。随后该变量可以在查询中使用, 也可以在结果中返回。

有三种语法形式允许这样做:BIND 关键字SELECT 子句中的表达式GROUP BY 子句中的表达式。赋值形式为 (expression AS ?var)

如果表达式求值产生错误,则该变量在该 解中保持未绑定,但查询求值继续。

也可以使用 VALUES 将数据作为内联数据直接包含在查询中。

10.1 BIND:赋值给变量

BIND 形式允许从基本图 模式或属性路径表达式将一个值赋给变量。使用 BIND 会结束前面的基本图 模式。由 BIND 子句引入的变量,在使用 BIND 的位置之前, 不得已在该组图模式中使用过。

示例:

数据:

PREFIX dc:   <http://purl.org/dc/elements/1.1/>
PREFIX :     <http://example.org/book/>
PREFIX ns:   <http://example.org/ns#>

:book1  dc:title     "SPARQL Tutorial" .
:book1  ns:price     42 .
:book1  ns:discount  0.2 .

:book2  dc:title     "The Semantic Web" .
:book2  ns:price     23 .
:book2  ns:discount  0.25 .

查询:

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>

SELECT  ?title ?price
{   
    ?x ns:price ?p .
    ?x ns:discount ?discount
    BIND (?p*(1-?discount) AS ?price)
    FILTER(?price < 20)
    ?x dc:title ?title . 
}

等价查询(BIND 结束基本图模式; FILTER 应用于整个组图模式):

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>

SELECT  ?title ?price
{  { ?x ns:price ?p .
     ?x ns:discount ?discount
     BIND (?p*(1-?discount) AS ?price)
    }
    {?x dc:title ?title . }
    FILTER(?price < 20)
}

结果:

title price
 "The Semantic Web" 17.25

10.2 VALUES:提供内联数据

数据可以直接写在图模式中,也可以使用 VALUES 加入查询。VALUES解序列的形式提供内联数据,该解序列通过 联接操作与查询求值结果组合。应用可使用它 对查询结果提供具体要求;提供通过 SERVICE 关键字进行联邦查询的 SPARQL 查询引擎 实现,也可以使用它向远程查询服务发送约束更强的查询。

10.2.1 VALUES 语法

VALUES 允许在数据块中指定多个变量;对于只指定一个变量和若干 值的常见情形,有一种特殊语法。

在以下示例中,有一个包含两个变量 ?x?y 的表。第二行没有 ?y 的值。

VALUES (?x ?y) {
    (:uri1 1)
    (:uri2 UNDEF)
}

可选地,当只有一个变量和若干值时:

VALUES ?z { "abc" "def" }

这与使用一般形式相同:

VALUES (?z) { ("abc") ("def") }

请注意,同一变量不能在 VALUES 子句的变量列表中被提及多次。

10.2.2 VALUES 示例

VALUES 数据块可以出现在查询模式中,也可以出现在 SELECT 查询的末尾,包括子查询

数据:

PREFIX dc:   <http://purl.org/dc/elements/1.1/>
PREFIX :     <http://example.org/book/>
PREFIX ns:   <http://example.org/ns#>

:book1  dc:title  "SPARQL Tutorial" .
:book1  ns:price  42 .
:book2  dc:title  "The Semantic Web" .
:book2  ns:price  23 .

查询:

PREFIX dc:   <http://purl.org/dc/elements/1.1/> 
PREFIX :     <http://example.org/book/> 
PREFIX ns:   <http://example.org/ns#> 

SELECT ?book ?title ?price
{
    VALUES ?book { :book1 :book3 }
    ?book dc:title ?title ;
          ns:price ?price .
}

结果:

book title price
<http://example.org/book/book1> "SPARQL Tutorial" 42

如果某个变量在 VALUES 子句中的特定解没有值, 则使用关键字 UNDEF 代替 RDF 项。

PREFIX dc:   <http://purl.org/dc/elements/1.1/> 
PREFIX :     <http://example.org/book/> 
PREFIX ns:   <http://example.org/ns#> 

SELECT ?book ?title ?price
{
    ?book dc:title ?title ;
          ns:price ?price .
    VALUES (?book ?title) {
        (UNDEF "SPARQL Tutorial")
        (:book2 UNDEF)
    }
}
book title price
<http://example.org/book/book1> "SPARQL Tutorial" 42
<http://example.org/book/book2> "The Semantic Web" 23

在此示例中,VALUES 也可以指定为在 SELECT 查询的结果上执行:

PREFIX dc:   <http://purl.org/dc/elements/1.1/> 
PREFIX :     <http://example.org/book/> 
PREFIX ns:   <http://example.org/ns#> 

SELECT ?book ?title ?price {
    ?book dc:title ?title ;
          ns:price ?price .
}
VALUES (?book ?title) {
    (UNDEF "SPARQL Tutorial")
    (:book2 UNDEF)
}

这是一个不同的查询,但在该示例情境下具有相同结果。

11. 聚合

聚合会把表达式应用于解的分组。默认情况下,一个解集由 一个包含所有解的单一分组组成。

可以使用 GROUP BY 语法指定分组。

SPARQL 1.1 版本中定义的聚合包括 COUNTSUMMINMAXAVGGROUP_CONCATSAMPLE

当查询者希望看到基于一组解计算出的结果,而不是单个解时, 会使用聚合。例如查看某个特定 变量所取的最大值,而不是分别查看每个值。

11.1 聚合示例

数据:

PREFIX : <http://books.example/>

:org1 :affiliates :auth1, :auth2 .
:auth1 :writesBook :book1, :book2 .
:book1 :price 9 .
:book2 :price 5 .
:auth2 :writesBook :book3 .
:book3 :price 7 .
:org2 :affiliates :auth3 .
:auth3 :writesBook :book4 .
:book4 :price 7 .

查询:

PREFIX : <http://books.example/>
SELECT (SUM(?lprice) AS ?totalPrice)
WHERE {
    ?org :affiliates ?auth .
    ?auth :writesBook ?book .
    ?book :price ?lprice .
}
GROUP BY ?org
HAVING (SUM(?lprice) > 10)

结果:

totalPrice
21

此示例展示聚合的两个特性:GROUP BY,它按照 一个或多个表达式(在此例中为 ?org)对查询解进行分组;以及 HAVING,它类似于 FILTER 表达式,但作用于 分组,而不是单个解。

该示例通过按照 GROUP BY 表达式对解分组而产生(即所有 ?org 取某一特定值的解都位于 同一分组内),并在该分组上求值集函数 SUM。随后 用 HAVING 表达式过滤分组,该表达式移除所有 SUM(?lprice) 不大于 10 的分组。

在聚合查询和子查询中,出现在查询模式中但不在 GROUP BY 子句中的变量,只有在被聚合时,才可以被投影或用于 select 表达式。 SAMPLE 聚合可用于此目的。详情见关于 投影限制的章节。

应注意,按照函数的规则,聚合 表达式必须具有别名(同样类似于 BIND 子句,使用 关键字 AS),才能从查询或子查询中投影出来。在 上面的示例中,这是使用变量 ?totalPrice 完成的。如果 聚合投影变量使用的名称已在其他聚合投影中或 WHERE 子句中使用,则是错误。

11.2 GROUP BY

为了计算某个解的聚合值,首先将解划分为 一个或多个分组,然后为每个分组计算聚合值。

如果在查询层级中的 SELECTHAVINGORDER BY 中使用了聚合,但未使用 GROUP BY 项, 则这会被视为一个包含所有解的单一隐式分组。

GROUP BY 子句中可以使用绑定关键字 AS, 例如 GROUP BY (?x + ?y AS ?z)。这等价于 { ... BIND (?x + ?y AS ?z) } GROUP BY ?z

例如,给定一个解序列 S( {?x→2, ?y→3}, {?x→2, ?y→5}, {?x→6, ?y→7} ),我们 可能希望按照 ?x 的值对解分组,并计算每个分组中 ?y 值的平均值。

这可以写作:

SELECT (AVG(?y) AS ?avg)
WHERE {
    ?a :x ?x ;
    :y ?y .
}
GROUP BY ?x

11.3 HAVING

HAVING 作用于已分组的解集,其方式与 FILTER 作用于未分组的解集相同。

HAVING 表达式具有与分组查询投影相同的求值规则, 如下一节所述。

下面给出一个使用 HAVING 的示例。

PREFIX : <http://data.example/>
SELECT (AVG(?size) AS ?asize)
WHERE {
    ?x :size ?size
}
GROUP BY ?x
HAVING(AVG(?size) > 10)

这将返回按主语分组的平均 size,但只返回平均 size 大于 10 的分组。

11.4 聚合投影 限制

在使用分组的查询层级中(无论是显式使用 GROUP BY 子句, 还是在投影、HAVINGORDER BY 子句中使用聚合), 出现在该查询层级的投影或 SELECT 表达式中的每一次变量出现 必须满足以下条件之一:

如果这样的变量出现不满足这些条件之一,则该查询在语法上 无效。

例如,以下查询是合法的,因为 ?x 被给定为 GROUP BY 项。

PREFIX : <http://example.com/data/#>
SELECT ?x (MIN(?y) * 2 AS ?min)
WHERE {
    ?x :p ?y .
    ?x :q ?z .
} GROUP BY ?x (STR(?z))

请注意,投影 STR(?z) 是不合法的,因为该表达式既不是简单 变量, 也不是具名 GROUP BY 表达式。不过,如果使用 GROUP BY ?x (STR(?z) AS ?strZ), 就可以投影 ?strZ

其他使用不满足上述条件的变量的表达式,可以使用 SAMPLE 聚合从其分组中投影出来。

11.5 聚合示例(带 错误)

本节展示一个使用聚合的示例查询,说明在存在聚合时 如何处理结果中的错误。

数据:

PREFIX : <http://example.com/data/#>

:x :p 1, 2, 3, 4 .
:y :p 1, _:b2, 3, 4 .
:z :p 1.0, 2.0, 3.0, 4 .

查询:

PREFIX : <http://example.com/data/#>
SELECT ?g (AVG(?p) AS ?avg) ((MIN(?p) + MAX(?p)) / 2 AS ?c)
WHERE {
    ?g :p ?p .
}
GROUP BY ?g

结果:

g avg c
<http://example.com/data/#x> 2.5 2.5
<http://example.com/data/#y>
<http://example.com/data/#z> 2.5 2.5

请注意,:y 分组的绑定未包含在结果中,因为 Avg({1, _:b2, 3, 4}) 和 (_:b2 + 4) / 2 的求值是错误,从而从 解中移除了这些绑定。

12. 子查询

子查询是一种把 SPARQL 查询嵌入其他查询中的方式,通常用于实现 否则无法实现的结果,例如限制查询中某个 子表达式的结果数量。

由于 SPARQL 查询求值具有自底向上的性质,子查询会在逻辑上 首先求值,然后将结果投影到外层查询。

请注意,只有从子查询中投影出的变量才对外层查询可见,或 处于作用域内

12.1 示例

数据:

PREFIX : <http://people.example/>

:alice :name "Alice", "Alice Foo", "A. Foo" .
:alice :knows :bob, :carol .
:bob :name "Bob", "Bob Bar", "B. Bar" .
:carol :name "Carol", "Carol Baz", "C. Baz" .

为所有认识 Alice 且具有姓名的人返回一个姓名(排序顺序最低的那个)。

查询:

PREFIX : <http://people.example/>
PREFIX : <http://people.example/>

SELECT ?y ?minName
WHERE {
    :alice :knows ?y .
    {
      SELECT ?y (MIN(?name) AS ?minName)
      WHERE {
          ?y :name ?name .
      } GROUP BY ?y
    }
}

结果:

y minName
:bob "B. Bar"
:carol "C. Baz"

此结果通过首先求值内层查询而得到:

SELECT ?y (MIN(?name) AS ?minName)
WHERE {
    ?y :name ?name .
} GROUP BY ?y

这会产生以下解序列:

y minName
:alice "A. Foo"
:bob "B. Bar"
:carol "C. Baz"

它与外层查询的结果进行联接:

y
:bob
:carol

13. RDF 数据集

RDF 数据模型将信息表达为由主语、 谓语和宾语三元组组成的图。许多 RDF 数据存储保存多个 RDF 图,并记录 关于每个图的信息,从而允许应用进行涉及来自多个 图的信息的查询。

SPARQL 查询针对一个 RDF 数据集 [RDF12-CONCEPTS] 执行,该数据集表示一个 图的集合。RDF 数据集包含一个没有名称的图,即默认图,以及 零个或多个命名图,其中每个命名图由 IRI 或空白节点标识。SPARQL 查询 可以 将查询模式的不同部分与不同图匹配,如 13.3 查询数据集一节所述。

RDF 数据集可以包含零个命名图;RDF 数据集始终包含一个默认 图。查询不需要涉及匹配默认图;查询也可以只涉及 匹配命名图。

用于匹配基本图模式的图称为活动图。在 前面的章节中,所有查询都展示为针对单个图执行,即以 RDF 数据集的默认 图作为活动图。GRAPH 关键字用于在查询的一部分中使 活动图成为数据集中所有命名图之一。

13.1 RDF 数据集示例

RDF 数据集的定义 [RDF12-CONCEPTS] 并不限制命名图和默认 图之间的关系。信息可以在不同图中重复;图之间的关系也可以被 暴露出来。两种有用的安排是:

示例 1:
PREFIX dc: <http://purl.org/dc/elements/1.1/>

<http://example.org/bob>    dc:publisher  "Bob" .
<http://example.org/alice>  dc:publisher  "Alice" .

GRAPH <http://example.org/bob> {
    _:a foaf:name "Bob" .
    _:a foaf:mbox <mailto:bob@oldcorp.example.org> .
}

GRAPH <http://example.org/alice> {
    _:a foaf:name "Alice" .
    _:a foaf:mbox <mailto:alice@work.example.org> .
}

在此示例中,默认图包含两个命名 图的发布者名称。在此 示例中,命名图中的三元组在默认图中不可见。

示例 2:

RDF 数据可以通过 图的 RDF 合并 [RDF12-SEMANTICS] 来组合。RDF 数据集中一种可能的图安排 是让默认图成为命名图中部分或全部信息的 RDF 合并。

在下一个示例中,命名图包含与之前相同的三元组。RDF 数据集 在默认图中包含这些命名图的 RDF 合并, 并保持空白节点彼此不同。

PREFIX foaf: <http://xmlns.com/foaf/0.1/>

_:x foaf:name "Bob" .
_:x foaf:mbox <mailto:bob@oldcorp.example.org> .

_:y foaf:name "Alice" .
_:y foaf:mbox <mailto:alice@work.example.org> .

GRAPH <http://example.org/bob> {
    _:a foaf:name "Bob" .
    _:a foaf:mbox <mailto:bob@oldcorp.example.org> .
}

GRAPH <http://example.org/alice> {
    _:a foaf:name "Alice" .
    _:a foaf:mbox <mailto:alice@work.example> .
}

在 RDF 合并中,合并图中的空白节点不会与 被合并图中的空白节点共享。

13.2 指定 RDF 数据集

SPARQL 查询可以通过使用 FROM 子句和 FROM NAMED 子句来描述 RDF 数据集,从而指定用于匹配的数据集。 如果查询提供了这样的数据集描述,则会用它替代查询服务在未提供数据集描述时 会使用的任何数据集。RDF 数据集也可以在 SPARQL 协议 请求中指定,在 这种情况下,协议描述会覆盖查询本身中的任何描述。如果数据集描述 对服务不可接受,查询服务可以拒绝查询请求。

FROMFROM NAMED 关键字允许查询通过引用指定 RDF 数据集;它们表示该数据集应包含从给定 IRI(即给定 IRI 引用的绝对形式) 所标识资源的表示中获得的图。由若干 FROMFROM NAMED 子句产生的数据集是:

如果没有 FROM 子句,但有一个或多个 FROM NAMED 子句,则该数据集包含一个空图作为默认图。

13.2.1 指定默认 图

每个 FROM 子句包含一个 IRI,表示用于形成 默认图的图。这不会把该图作为命名图加入。

在此示例中,RDF 数据集包含一个默认图且没有命名 图:

# Default graph (located at http://example.org/foaf/aliceFoaf)
PREFIX  foaf:  <http://xmlns.com/foaf/0.1/>

_:a  foaf:name     "Alice" .
_:a  foaf:mbox     <mailto:alice@work.example> .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT  ?name
FROM    <http://example.org/foaf/aliceFoaf>
WHERE   { ?x foaf:name ?name }
name
"Alice"

如果查询提供多个 FROM 子句,即提供多个 IRI 来表示默认图,则默认图是 从给定 IRI 所标识资源的表示中取得的图的 RDF 合并

13.2.2 指定命名图

查询可以使用 FROM NAMED 子句为 RDF 数据集中的命名图提供 IRI。每个 IRI 用于在 RDF 数据集中提供一个命名图。 在两个或更多 FROM NAMED 子句中使用 同一 IRI,会导致数据集中出现一个具有该 IRI 的命名图。

# Graph: http://example.org/bob
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

_:a foaf:name "Bob" .
_:a foaf:mbox <mailto:bob@oldcorp.example.org> .
# Graph: http://example.org/alice
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

_:a foaf:name "Alice" .
_:a foaf:mbox <mailto:alice@work.example> .
...
FROM NAMED <http://example.org/alice>
FROM NAMED <http://example.org/bob>
...

FROM NAMED 语法暗示 IRI 标识相应的 图,但 RDF 数据集中 IRI 与图之间的关系是间接的。IRI 标识一个资源,而该资源由一个图表示(或者更准确地说: 由一个序列化图的文档表示)。更多 详细信息 见 [WEBARCH]。

13.2.3 组合 FROM 和 FROM NAMED

FROM 子句和 FROM NAMED 子句可以在同一 查询中使用。

# Default graph (located at http://example.org/dft.ttl)
PREFIX dc: <http://purl.org/dc/elements/1.1/>

<http://example.org/bob>    dc:publisher  "Bob Hacker" .
<http://example.org/alice>  dc:publisher  "Alice Hacker" .
# Named graph: http://example.org/bob
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

_:a foaf:name "Bob" .
_:a foaf:mbox <mailto:bob@oldcorp.example.org> .
# Named graph: http://example.org/alice
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

_:a foaf:name "Alice" .
_:a foaf:mbox <mailto:alice@work.example.org> .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT ?who ?g ?mbox
FROM <http://example.org/dft.ttl>
FROM NAMED <http://example.org/alice>
FROM NAMED <http://example.org/bob>
WHERE
{
    ?g dc:publisher ?who .
    GRAPH ?g { ?x foaf:mbox ?mbox }
}

此查询的 RDF 数据集包含一个默认图和两个命名图。 GRAPH 关键字在下文描述。

构造数据集所需的动作不能仅由数据集 描述确定。如果某个 IRI 在数据集描述中出现两次,无论是使用两个 FROM 子句,还是一个 FROM 子句和一个 FROM NAMED 子句,都不意味着会恰好进行一次或恰好两次尝试来获取 与该 IRI 关联的 RDF 图。因此,不能对从数据集描述中这两次出现获得的三元组中的空白 节点身份作出假设。一般而言,也不能对这些图的等价性作出假设。

13.3 查询数据集

查询一组图时,使用 GRAPH 关键字将 模式与命名图匹配。GRAPH 可以提供一个 IRI 来选择一个图, 也可以使用一个变量,该变量会遍历查询的 RDF 数据集中所有命名图的 IRI。

使用 GRAPH 会改变查询中该部分内 图模式匹配所用的活动图。在 GRAPH 使用范围之外, 使用默认图进行匹配。

以下两个图将用于示例:

# Named graph: http://example.org/foaf/aliceFoaf
PREFIX  foaf:     <http://xmlns.com/foaf/0.1/>
PREFIX  rdf:      <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX  rdfs:     <http://www.w3.org/2000/01/rdf-schema#>

_:a  foaf:name     "Alice" .
_:a  foaf:mbox     <mailto:alice@work.example> .
_:a  foaf:knows    _:b .

_:b  foaf:name     "Bob" .
_:b  foaf:mbox     <mailto:bob@work.example> .
_:b  foaf:nick     "Bobby" .
_:b  rdfs:seeAlso  <http://example.org/foaf/bobFoaf> .

<http://example.org/foaf/bobFoaf>
rdf:type      foaf:PersonalProfileDocument .
# Named graph: http://example.org/foaf/bobFoaf
PREFIX  foaf:     <http://xmlns.com/foaf/0.1/>
PREFIX  rdf:      <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX  rdfs:     <http://www.w3.org/2000/01/rdf-schema#>

_:z  foaf:mbox     <mailto:bob@work.example> .
_:z  rdfs:seeAlso  <http://example.org/foaf/bobFoaf> .
_:z  foaf:nick     "Robert" .

<http://example.org/foaf/bobFoaf>
        rdf:type      foaf:PersonalProfileDocument .

13.3.1 访问图名称

下面的查询将图模式与数据集中的每个命名图匹配, 并形成这样的解:src 变量绑定到 正在匹配的图的 IRI。图模式在活动图分别为数据集中各 命名图的情况下进行匹配。

PREFIX foaf: <http://xmlns.com/foaf/0.1/>

SELECT ?src ?bobNick
FROM NAMED <http://example.org/foaf/aliceFoaf>
FROM NAMED <http://example.org/foaf/bobFoaf>
WHERE
{
    GRAPH ?src
    { ?x foaf:mbox <mailto:bob@work.example> .
      ?x foaf:nick ?bobNick
    }
}

查询结果给出找到该信息的图名称以及 Bob 昵称的 值:

src bobNick
<http://example.org/foaf/aliceFoaf> "Bobby"
<http://example.org/foaf/bobFoaf> "Robert"

13.3.2 按图 IRI 进行限制

查询可以通过提供图 IRI,把所应用的匹配限制到特定图。 这会将活动图设置为由该 IRI 命名的图。此查询查找 图 http://example.org/foaf/bobFoaf 中给出的 Bob 昵称。

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX data: <http://example.org/foaf/>

SELECT ?nick
FROM NAMED <http://example.org/foaf/aliceFoaf>
FROM NAMED <http://example.org/foaf/bobFoaf>
WHERE
{
    GRAPH data:bobFoaf {
        ?x foaf:mbox <mailto:bob@work.example> .
        ?x foaf:nick ?nick 
    }
}

它产生一个解:

nick
"Robert"

13.3.3 限制 可能的图 IRI

GRAPH 子句中使用的变量,也可以用于另一个 GRAPH 子句,或用于与数据集中的默认图匹配的图模式。

下面的查询使用 IRI 为 http://example.org/foaf/aliceFoaf 的图来查找 Bob 的资料文档;随后它将另一个模式与该图匹配。 第二个 GRAPH 子句中的模式会找到 与第一个 GRAPH 子句中找到的邮箱(变量 mbox) 相同的人员的空白节点(变量 w),这是因为 从 Alice 的 FOAF 文件匹配变量 whom 时使用的 空白节点,与资料文档中的空白节点并不相同(它们位于不同图中)。

PREFIX  data:  <http://example.org/foaf/>
PREFIX  foaf:  <http://xmlns.com/foaf/0.1/>
PREFIX  rdfs:  <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?mbox ?nick ?ppd
FROM NAMED <http://example.org/foaf/aliceFoaf>
FROM NAMED <http://example.org/foaf/bobFoaf>
WHERE {
    GRAPH data:aliceFoaf {
        ?alice foaf:mbox <mailto:alice@work.example> ;
               foaf:knows ?whom .
        ?whom  foaf:mbox ?mbox ;
               rdfs:seeAlso ?ppd .
        ?ppd  a foaf:PersonalProfileDocument .
    }
    GRAPH ?ppd {
        ?w foaf:mbox ?mbox ;
           foaf:nick ?nick
    }
}
mbox nick ppd
<mailto:bob@work.example> "Robert" <http://example.org/foaf/bobFoaf>

Alice 的 FOAF 文件中给出 Bob 的 nick 的任何三元组,都不会用于为 Bob 提供 nick,因为涉及变量 nick 的模式被 ppd 限制到特定的个人资料文档。

13.3.4 命名图与默认图

查询模式可以同时涉及默认图和命名图。在此示例中, 一个聚合器在两个不同时间读取了一个 Web 资源。每次将图读入 聚合器时,本地系统都会为其赋予一个 IRI。这些图几乎 相同,但“Bob”的电子邮件地址发生了变化。

在此示例中,默认图用于记录来源信息, 实际读取的 RDF 数据保存在两个独立图中,每个图都由系统赋予一个 不同的 IRI。RDF 数据集由两个命名图和关于它们的 信息组成。

RDF 数据集:

# Default graph
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX g:  <tag:example.org,2005-06-06:>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

g:graph1 dc:publisher "Bob" .
g:graph1 dc:date "2004-12-06"^^xsd:date .

g:graph2 dc:publisher "Bob" .
g:graph2 dc:date "2005-01-10"^^xsd:date .
# Graph: locally allocated IRI: tag:example.org,2005-06-06:graph1
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

_:a foaf:name "Alice" .
_:a foaf:mbox <mailto:alice@work.example> .

_:b foaf:name "Bob" .
_:b foaf:mbox <mailto:bob@oldcorp.example.org> .
# Graph: locally allocated IRI: tag:example.org,2005-06-06:graph2
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

_:a foaf:name "Alice" .
_:a foaf:mbox <mailto:alice@work.example> .

_:b foaf:name "Bob" .
_:b foaf:mbox <mailto:bob@newcorp.example.org> .

此查询查找电子邮件地址,并详细说明人员姓名以及发现该 信息的日期。

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc:   <http://purl.org/dc/elements/1.1/>

SELECT ?name ?mbox ?date
WHERE {
   ?g dc:publisher ?name ;
      dc:date ?date .
   GRAPH ?g { 
       ?person foaf:name ?name ; foaf:mbox ?mbox
   }
}

结果表明“Bob”的电子邮件地址已经改变。

name mbox date
"Bob" <mailto:bob@oldcorp.example.org> "2004-12-06"^^xsd:date
"Bob" <mailto:bob@newcorp.example.org> "2005-01-10"^^xsd:date

14. 基本联邦查询

本文档纳入了 SPARQL 联邦扩展的语法。

此特性定义于文档 SPARQL 1.1 联邦查询

15. 解序列与修饰符

查询模式会生成一个无序的解集合,每个 都是从变量到 RDF 项的偏函数。随后这些解被视为一个序列(解序列),初始时没有 特定顺序;之后应用任何序列修饰符来创建另一个序列。最后, 后一个序列用于生成 SPARQL 查询形式的某一种结果。

解序列修饰符是以下之一:

修饰符按上面列表给出的顺序应用。

15.1 ORDER BY

ORDER BY 子句确定解序列的顺序。

ORDER BY 子句之后是一系列排序比较器,由 一个表达式和一个可选的排序修饰符(ASC()DESC())组成。每个排序比较器要么是升序(由 ASC() 修饰符表示,或没有修饰符),要么是降序(由 DESC() 修饰符表示)。

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>

SELECT ?name
WHERE { ?x foaf:name ?name }
ORDER BY ?name
PREFIX     :    <http://example.org/ns#>
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>

SELECT ?name
WHERE { ?x foaf:name ?name ; :empId ?emp }
ORDER BY DESC(?emp)
PREFIX     :    <http://example.org/ns#>
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>

SELECT ?name
WHERE { ?x foaf:name ?name ; :empId ?emp }
ORDER BY ?name DESC(?emp)

“<”运算符(见运算符 映射运算符可扩展性)定义 numericsxsd:stringsxsd:booleansxsd:dateTimes 成对值的相对顺序。IRI 对通过把它们作为数据类型为 xsd:string 的字面量进行比较来排序。

SPARQL 还在某些否则不会排序的 RDF 项种类之间固定了顺序:

  1. (最低)此解中没有给变量或表达式分配值。
  2. 空白节点
  3. IRI
  4. RDF 字面量
  5. 三元组项

SPARQL 并未定义所有可能 RDF 项的全序。实现可以 通过运算符可扩展性定义全序。以下是一些 相对顺序未定义的项对示例:

以下变量绑定列表按升序排列:

RDF 项 原因
未绑定结果排序最靠前。
_:z 空白节点跟在未绑定之后。
_:a 空白节点之间没有相对顺序。
<http://script.example/Latin> IRI 跟在空白节点之后。
<http://script.example/Кириллица> 第 23 个位置的字符“К”的 unicode 码位为 0x41A,高于 0x4C(“L”)。
<http://script.example/漢字> 第 23 个位置的字符“漢”的 unicode 码位为 0x6F22,高于 0x41A(“К”)。
"http://script.example/Latin" xsd:strings 跟在 IRI 之后。

两个解相对于某个排序比较器的升序,是通过将解绑定代入表达式, 并使用 “<”运算符比较它们来确定的。降序 是升序的反向。

两个解的相对顺序,是两个解相对于序列中第一个排序比较器的 相对顺序。对于那些解绑定的代入产生相同 RDF 项的解, 顺序是两个解相对于下一个排序比较器的相对 顺序。如果没有任何排序表达式在两个解上的求值产生 不同的 RDF 项,则两个解的相对顺序未定义。

对解序列排序总会得到一个包含相同数量 解的序列。

CONSTRUCTDESCRIBE 查询的解序列上使用 ORDER BY 没有直接影响, 因为只有 SELECT 返回结果序列。与 LIMITOFFSET 结合使用时, ORDER BY 可用于返回从解序列的不同切片生成的结果。 ASK 查询不包含 ORDER BYLIMITOFFSET

15.2 投影

解序列可以转换为只涉及变量子集的序列。 对于序列中的每个解,会使用 SELECT 查询形式指定选择的变量来形成 一个新解。

以下示例展示一个查询,用于使用 FOAF 属性从 RDF 图中提取所描述人员的姓名。

PREFIX foaf:        <http://xmlns.com/foaf/0.1/>

_:a  foaf:name       "Alice" .
_:a  foaf:mbox       <mailto:alice@work.example> .

_:b  foaf:name       "Bob" .
_:b  foaf:mbox       <mailto:bob@work.example> .
PREFIX foaf:       <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE
{ ?x foaf:name ?name }
name
"Bob"
"Alice"

15.3 重复解

没有 DISTINCTREDUCED 查询修饰符的 解序列会保留重复解。

数据:

PREFIX  foaf:  <http://xmlns.com/foaf/0.1/>

_:x    foaf:name   "Alice" .
_:x    foaf:mbox   <mailto:alice@example.com> .

_:y    foaf:name   "Alice" .
_:y    foaf:mbox   <mailto:asmith@example.com> .

_:z    foaf:name   "Alice" .
_:z    foaf:mbox   <mailto:alice.smith@example.com> .

查询:

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
SELECT ?name WHERE { ?x foaf:name ?name }

结果:

name
"Alice"
"Alice"
"Alice"

DISTINCTREDUCED 修饰符会影响查询结果中 是否包含重复项。

DISTINCT

DISTINCT 解修饰符会消除重复解。对于 将相同变量绑定到相同 RDF 项的解,查询只返回一个 解。

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
SELECT DISTINCT ?name WHERE { ?x foaf:name ?name }
name
"Alice"

请注意,根据解 序列修饰符的顺序,重复项会在应用 limit 或 offset 之前被 消除。

REDUCED

DISTINCT 修饰符确保从解集中消除 重复解,而 REDUCED 只是允许消除它们。 REDUCED 解集中任何解的重数至少为一,且不超过在 没有 DISTINCTREDUCED 修饰符的解集中的 该解重数。例如,使用上面的数据,查询

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
SELECT REDUCED ?name WHERE { ?x foaf:name ?name }

可能有一个、两个(此处显示)或三个解:

name
"Alice"
"Alice"

15.4 OFFSET

OFFSET 使生成的解从指定数量的 解之后开始。OFFSET 为零没有影响。

使用 LIMITOFFSET 选择查询 解的不同子集不会有用,除非通过使用 ORDER BY 使顺序可预测。

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>

SELECT  ?name
WHERE   { ?x foaf:name ?name }
ORDER BY ?name
LIMIT   5
OFFSET  10

15.5 LIMIT

LIMIT 子句为返回的解数量设置上限。如果 在应用 OFFSET 后,实际解的数量大于该 限制,则最多返回该限制数量的解。

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>

SELECT ?name
WHERE { ?x foaf:name ?name }
LIMIT 20

LIMIT 为 0 会导致不返回任何结果。limit 不得为 负数。

16. 查询形式

SPARQL 有四种查询形式。这些查询形式使用模式匹配得到的解来 形成结果集或 RDF 图。查询形式为:

SELECT
返回查询模式匹配中绑定变量的全部或子集。
CONSTRUCT
通过在一组三元组模板中替换变量,返回构造出的 RDF 图。
ASK
返回一个布尔值,表示查询模式是否匹配。
DESCRIBE
返回描述所找到资源的 RDF 图。

诸如 SPARQL 1.1 查询结果 JSON 格式SPARQL 查询结果 XML 格式(第二版)SPARQL 1.1 查询结果 CSV 和 TSV 格式等格式可用于序列化 SELECT 查询的结果集或 ASK 查询的布尔结果。

16.1 SELECT

SELECT 结果形式直接返回变量及其绑定。它把 投影所需变量的操作与在查询解中引入新变量绑定的操作结合起来。

16.1.1 投影

当在 SELECT 子句中给出变量名列表时,会返回 特定变量及其绑定。语法 SELECT * 是一种缩写, 它选择查询中该位置处于作用域内的所有变量。 它排除只在 FILTER 中使用的变量、MINUS 右侧 使用的变量,并考虑子查询。

只有当查询不使用分组时(无论是通过使用 GROUP BY 子句, 还是由于 HAVINGORDER BY 子句中存在聚合), 才允许使用 SELECT *

PREFIX  foaf:  <http://xmlns.com/foaf/0.1/>

_:a    foaf:name   "Alice" .
_:a    foaf:knows  _:b .
_:a    foaf:knows  _:c .

_:b    foaf:name   "Bob" .

_:c    foaf:name   "Clare" .
_:c    foaf:nick   "CT" .
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
SELECT ?nameX ?nameY ?nickY
WHERE
{ ?x foaf:knows ?y ;
  foaf:name ?nameX .
  ?y foaf:name ?nameY .
  OPTIONAL { ?y foaf:nick ?nickY }
}
nameX nameY nickY
"Alice" "Bob"
"Alice" "Clare" "CT"

结果集可以通过本地 API 访问,也可以序列化为 JSON、XML、CSV 或 TSV。

SPARQL 1.1 查询结果 JSON 格式

{
    "head": {
        "vars": [ "nameX" , "nameY" , "nickY" ]
    } ,
    "results": {
        "bindings": [
          {
            "nameX": { "type": "literal" , "value": "Alice" } ,
            "nameY": { "type": "literal" , "value": "Bob" }
          } ,
          {
            "nameX": { "type": "literal" , "value": "Alice" } ,
            "nameY": { "type": "literal" , "value": "Clare" } ,
            "nickY": { "type": "literal" , "value": "CT" }
          }
        ]
    }
}

SPARQL 查询结果 XML 格式 (第二版)

<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
<head>
<variable name="nameX"/>
<variable name="nameY"/>
<variable name="nickY"/>
</head>
<results>
<result>
<binding name="nameX">
<literal>Alice</literal>
</binding>
<binding name="nameY">
<literal>Bob</literal>
</binding>
</result>
<result>
<binding name="nameX">
<literal>Alice</literal>
</binding>
<binding name="nameY">
<literal>Clare</literal>
</binding>
<binding name="nickY">
<literal>CT</literal>
</binding>
</result>
</results>
</sparql>

16.1.2 SELECT 表达式

除了选择模式匹配中的哪些变量包含在 结果中之外,SELECT 子句还可以引入新变量。SELECT 表达式中的赋值规则 与 BIND 中的赋值规则相同。表达式会组合查询解中已有的变量 绑定,或同一 SELECT 子句中更早定义的变量绑定,以在查询解中产生 一个绑定。

(expr AS v) 的作用域立即生效。在 SELECT 表达式中,该变量可以在同一 SELECT 子句后面的表达式中使用,并且不得在同一 SELECT 子句中再次赋值。

示例:

数据:

PREFIX dc:   <http://purl.org/dc/elements/1.1/>
PREFIX :     <http://example.org/book/>
PREFIX ns:   <http://example.org/ns#>

:book1  dc:title  "SPARQL Tutorial" .
:book1  ns:price  42 .
:book1  ns:discount 0.2 .

:book2  dc:title  "The Semantic Web" .
:book2  ns:price  23 .
:book2  ns:discount 0.25 .

查询:

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>
SELECT  ?title (?p*(1-?discount) AS ?price)
{ ?x ns:price ?p .
  ?x dc:title ?title . 
  ?x ns:discount ?discount 
}

结果:

title price
"The Semantic Web" 17.25
"SPARQL Tutorial" 33.6

如果新变量在语法上于同一 SELECT 子句中更早引入, 也可以在表达式中使用:

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>
SELECT  ?title (?p AS ?fullPrice) (?fullPrice*(1-?discount) AS ?customerPrice)
{ ?x ns:price ?p .
  ?x dc:title ?title . 
  ?x ns:discount ?discount 
}

结果:

title fullPrice customerPrice
"The Semantic Web" 23 17.25
"SPARQL Tutorial" 42 33.6

16.2 CONSTRUCT

CONSTRUCT 查询形式返回由图 模板指定的单个 RDF 图。结果是一个 RDF 图,其形成方式是对解序列中的每个查询解, 替换图模板中的变量,并通过集合并集将三元组 合并为一个单一 RDF 图。

如果任何这样的实例化产生了包含未绑定变量或非法 RDF 结构的三元组,例如字面量处于主语或谓语位置, 则该三元组不会包含在输出 RDF 图中。图模板可以包含没有变量的三元组 (称为基三元组或显式三元组),这些三元组也会出现在 CONSTRUCT 查询形式返回的输出 RDF 图中。

通过“集合并集”构造结果图并不 强制图序列化中是否出现重复三元组。 允许实现产生重复三元组或对其去重。

PREFIX  foaf:  <http://xmlns.com/foaf/0.1/>

_:a    foaf:name   "Alice" .
_:a    foaf:mbox   <mailto:alice@example.org> .
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
PREFIX vcard:   <http://www.w3.org/2001/vcard-rdf/3.0#>
CONSTRUCT   { <http://example.org/person#Alice> vcard:FN ?name }
WHERE       { ?x foaf:name ?name }

从 FOAF 信息创建 vcard 属性:

PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>

<http://example.org/person#Alice> vcard:FN "Alice" .

16.2.1 带空白 节点的模板

模板可以创建包含空白节点的 RDF 图。 模板内的空白节点标识符对于每个解的作用域限定于 该模板,而来自查询解的空白节点 不受该作用域限制。 如果同一标识符在模板中出现两次,则每次出现 都会被替换为为每个 查询解创建的同一个空白节点,并且由不同查询解生成的三元组 会有不同的空白节点。

PREFIX  foaf:  <http://xmlns.com/foaf/0.1/>

_:a    foaf:givenname   "Alice" .
_:a    foaf:family_name "Hacker" .

_:b    foaf:firstname   "Bob" .
_:b    foaf:surname     "Hacker" .
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
PREFIX vcard:   <http://www.w3.org/2001/vcard-rdf/3.0#>

CONSTRUCT {
     ?x  vcard:N _:v .
    _:v vcard:givenName ?gname .
    _:v vcard:familyName ?fname
} WHERE {
    { ?x foaf:firstname ?gname } UNION  { ?x foaf:givenname   ?gname } .
    { ?x foaf:surname   ?fname } UNION  { ?x foaf:family_name ?fname } .
}

创建与 FOAF 信息对应的 vcard 属性:

PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>

_:a vcard:N         _:v1 .
_:v1 vcard:givenName  "Alice" .
_:v1 vcard:familyName "Hacker" .

_:b vcard:N         _:v2 .
_:v2 vcard:givenName  "Bob" .
_:v2 vcard:familyName "Hacker" .

模板中标识符为 _:v 的空白节点 在模板应用于两个查询解中的每一个时, 会被不同的空白节点替换。 在此示例中,这会导致模板在 结果图中生成标识符为 _:v1_:v2 的空白节点。

查询解中的空白节点,以标识符 _:a_:b 显示,源自底层 RDF 数据集,不会被改变。

16.2.2 访问 RDF 数据集中的图

使用 CONSTRUCT,可以从目标 RDF 数据集中提取图的部分或全部。 第一个示例返回 IRI 标签为 http://example.org/aGraph 的图(如果它在数据集中); 否则返回一个空图。

CONSTRUCT { ?s ?p ?o } WHERE { GRAPH <http://example.org/aGraph> { ?s ?p ?o } . }

对图的访问可以以其他信息为条件。例如,如果 默认图包含关于数据集中命名图的元数据,那么如下查询可以 基于有关命名图的信息提取一个图:

PREFIX  dc: <http://purl.org/dc/elements/1.1/>
PREFIX app: <http://example.org/ns#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

CONSTRUCT { ?s ?p ?o } WHERE
{
    GRAPH ?g { ?s ?p ?o } .
    ?g dc:publisher <http://www.w3.org/> .
    ?g dc:date ?date .
    FILTER ( app:customDate(?date) > "2005-02-28T00:00:00Z"^^xsd:dateTime ) .
}

其中 app:customDate 标识一个扩展 函数,用于将日期格式转换为 xsd:dateTime RDF 项。

16.2.3 解修饰符 与 CONSTRUCT

查询的解修饰符会影响 CONSTRUCT 查询的结果。 在此示例中,CONSTRUCT 模板的输出图仅来自 图模式匹配的两个解。该查询输出一个图,其中包含按 hits 排名前两个站点的人员姓名。 RDF 图中的三元组没有顺序。

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX site: <http://example.org/stats#>

_:a foaf:name "Alice" .
_:a site:hits 2349 .

_:b foaf:name "Bob" .
_:b site:hits 105 .

_:c foaf:name "Eve" .
_:c site:hits 181 .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX site: <http://example.org/stats#>

CONSTRUCT { [] foaf:name ?name }
WHERE
{ [] foaf:name ?name ;
  site:hits ?hits .
}
ORDER BY desc(?hits)
LIMIT 2
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
_:x foaf:name "Alice" .
_:y foaf:name "Eve" .

16.2.4 CONSTRUCT WHERE

对于模板和模式相同,并且该模式只是一个基本图模式的情况, 提供了 CONSTRUCT 查询形式的简短形式(简短形式中不允许 FILTER,也不允许复杂图模式)。 简短形式中要求使用关键字 WHERE

以下两个查询相同;第一个是第二个的简短形式。

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
CONSTRUCT WHERE { ?x foaf:name ?name }
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

CONSTRUCT { ?x foaf:name ?name } 
WHERE
{ ?x foaf:name ?name }

16.3 ASK

应用可以使用 ASK 形式来测试查询模式是否 有解。它不返回关于可能查询解的信息,只返回是否 存在解。

PREFIX foaf:       <http://xmlns.com/foaf/0.1/>

_:a  foaf:name       "Alice" .
_:a  foaf:homepage   <http://work.example.org/alice/> .

_:b  foaf:name       "Bob" .
_:b  foaf:mbox       <mailto:bob@work.example> .
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
ASK  { ?x foaf:name  "Alice" }
true

此结果集的 SPARQL 查询结果 XML 格式(第二 版)形式为:

<?xml version="1.0"?>
                <sparql xmlns="http://www.w3.org/2005/sparql-results#">
                <head></head>
                <boolean>true</boolean>
                </sparql>

在相同数据上,以下查询返回不匹配,因为 Alice 的 mbox 未被提及。

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
ASK  {
   ?x foaf:name  "Alice" ;
      foaf:mbox  <mailto:alice@work.example>
}
false

16.4 DESCRIBE(资料性)

DESCRIBE 形式返回一个包含关于 资源的 RDF 数据的单个结果 RDF 图。该数据不是由 SPARQL 查询规定的, 因为查询客户端需要知道数据源中 RDF 的结构;相反,它由 SPARQL 查询处理器确定。查询模式用于创建结果集。 DESCRIBE 形式会取得解中标识的每个资源, 连同任何由 IRI 直接命名的资源,并通过获取一个 “描述”来组装单个 RDF 图,该描述可以来自包括目标 RDF 数据集在内的任何可用信息。 描述由查询服务确定。语法 DESCRIBE * 是一种 缩写,用于描述查询中的所有变量。

16.4.1 显式 IRI

DESCRIBE 子句本身可以接受 IRI 来标识资源。 最简单的 DESCRIBE 查询就是 DESCRIBE 子句中的一个 IRI:

DESCRIBE <http://example.org/>

16.4.2 标识资源

要描述的资源也可以从结果集中查询变量的绑定取得。 这使得无论资源在数据集中由 IRI 标识还是由空白节点标识, 都可以描述该资源:

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
DESCRIBE ?x
WHERE    { ?x foaf:mbox <mailto:alice@org> }

属性 foaf:mbox 在 FOAF 词汇表中被定义为逆函数属性。 如果按此处理,此查询最多会返回关于一个人的信息。 但是,如果查询模式有多个解,则每个解的 RDF 数据是所有 RDF 图描述的并集。

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
DESCRIBE ?x
WHERE    { ?x foaf:name "Alice" }

可以给出多个 IRI 或变量:

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
DESCRIBE ?x ?y <http://example.org/>
WHERE    {?x foaf:knows ?y}

16.4.3 资源描述

返回的 RDF 由信息发布者确定。它可以是服务认为 与被描述资源相关的信息。它可以包含关于 其他资源的信息:例如,某本书的 RDF 数据也可能包含关于 作者的详细信息。

一个简单查询,例如

PREFIX ent:  <http://org.example.com/employees#>
DESCRIBE ?x WHERE { ?x ent:employeeId "1234" }

可能返回该员工的描述以及其他一些潜在有用的 详细信息:

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
PREFIX vcard:  <http://www.w3.org/2001/vcard-rdf/3.0>
PREFIX exOrg:  <http://org.example.com/employees#>
PREFIX rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl:    <http://www.w3.org/2002/07/owl#>

_:a     exOrg:employeeId    "1234" ;
        foaf:mbox_sha1sum   "bee135d3af1e418104bc42904596fe148e90f033" ;
        vcard:N
          [ vcard:Family       "Smith" ;
            vcard:Given        "John"  ] .
foaf:mbox_sha1sum  rdf:type  owl:InverseFunctionalProperty .

其中包含 vCard 词汇表 vcard:N 的空白节点闭包。 决定返回哪些 信息的其他可能机制包括简明有界描述 [CBD]。

对于 FOAF 这样的词汇表,其中资源通常是空白节点,返回 足以标识节点的信息(例如 InverseFunctionalProperty foaf:mbox_sha1sum)以及姓名和记录的其他详细信息, 会是适当的。在示例中,返回了与 WHERE 子句的匹配, 但这不是必需的。

17. 表达式与值测试

SPARQL FILTER 会根据给定的 约束限制图模式匹配的解。具体而言,FILTER 会消除 这样的解:当把这些解代入表达式时,要么得到有效布尔值 false,要么产生错误。有效布尔值定义于 有效布尔值一节,错误定义于 求值错误

RDF 字面量具有决定该字面量值的数据类型。

PREFIX a:          <http://www.w3.org/2000/10/annotation-ns#>
PREFIX dc:         <http://purl.org/dc/elements/1.1/>

_:a   a:annotates   <http://www.w3.org/TR/rdf-sparql-query/> .
_:a   dc:date       "2004-12-31T19:00:00-05:00" .

_:b   a:annotates   <http://www.w3.org/TR/rdf-sparql-query/> .
_:b   dc:date       "2004-12-31T19:01:00-05:00"^^<http://www.w3.org/2001/XMLSchema#dateTime> .

第一个 dc:date 三元组的宾语是一个 数据类型为 xsd:string 的字面量。 第二个具有数据类型 xsd:dateTime。 它们是不同的 RDF 项, 具有不同的值。

SPARQL 表达式按照文法构造,并提供对函数(由 IRI 命名)和 运算符函数(由 SPARQL 文法中的关键字和符号调用)的访问。SPARQL 运算符可用于比较字面量的值:

PREFIX a:      <http://www.w3.org/2000/10/annotation-ns#>
PREFIX dc:     <http://purl.org/dc/elements/1.1/>
PREFIX xsd:    <http://www.w3.org/2001/XMLSchema#>

SELECT ?annot
WHERE { ?annot  a:annotates  <http://www.w3.org/TR/rdf-sparql-query/> .
        ?annot  dc:date      ?date .
        FILTER ( ?date > "2005-01-01T00:00:00Z"^^xsd:dateTime ) 
}

SPARQL 运算符列于第 17.3 节,并与文法中的 相应产生式相关联。

此外,SPARQL 提供调用任意函数的能力,包括 第 17.5 节列出的一部分 XPath 转换函数。这些 函数在 SPARQL 查询中按名称(一个 IRI)调用。例如:

... FILTER ( xsd:dateTime(?date) < xsd:dateTime("2005-01-01T00:00:00Z") ) ...

排版约定:XPath 运算符用前缀 op: 标记。XPath 运算符没有命名空间;op: 是一种标记 约定。

在 SPARQL 中,XPath 和 XQuery 函数与运算符 3.1 [XPATH-FUNCTIONS-31] 中依赖 XML 和 XML Schema 的定义 必须使用 可扩展标记语言(XML)1.1(第二版) [XML11] 和 W3C XML Schema 定义语言(XSD)1.1 第 2 部分:数据类型 [XMLSCHEMA11-2]

XML 1.0 与 1.1 以及 XML Schema 1.0 与 1.1 的使用,在 XPath 和 XQuery 函数与运算符 3.1中是 由实现定义的。 这尤其影响 Char 的定义, 该定义在 可扩展标记语言(XML)1.1(第二 版)中更为通用。

17.1 操作数数据类型

SPARQL 函数和运算符作用于 RDF 项和 SPARQL 变量。其中一部分 函数和运算符取自 XPath 和 XQuery 函数与运算符 3.1 [XPATH-FUNCTIONS-31],并具有 XML Schema 类型化 值参数和返回类型。作为参数传给这些函数和运算符的 RDF literals 会映射为 XML Schema 类型化值,其 字符串值lexical form,并具有与 datatype IRI 对应的 原子数据类型。返回的类型化值会以相同方式映射回 RDF literals

SPARQL 还有一些作用于 RDF 项特定子集的附加运算符。引用 类型时,以下术语表示具有相应 W3C XML Schema 定义语言(XSD)1.1 第 2 部分: 数据类型 [XMLSCHEMA11-2] datatype IRIliteral

以下术语标识 SPARQL 值测试中使用的附加类型:

以下类型派生自 numeric 类型,并且是接受 numeric 参数的函数和运算符的有效参数:

SPARQL 语言扩展可以将附加类型视为派生自 XML schema 数据类型。

17.2 表达式求值

SPARQL 表达式相对于一个解映射, 并在具有活动图RDF 数据集上下文中进行求值。 这种求值的结果要么是一个 RDF 项,要么是一个 错误

SPARQL 提供由 XPath 和 XQuery 函数与 运算符定义的函数和运算符的一个子集。 以下规则适配 XPath/XQuery 与 SPARQL 之间数据模型和执行模型的差异:

true(T)、false (F)和 error(E)的 logical-and 与 logical-or 真值表如下:

A B A || B A && B
T T T T
T F T F
F T T F
F F F F
T E T E
E T T E
F E E F
E F E F
E E E E

17.2.1 调用

SPARQL 定义了用于在参数列表上调用函数的语法。除非另有 说明,这些函数按如下方式调用:

  • 对参数表达式求值,产生参数值。参数 求值的顺序未定义。
  • 数值参数会按需要提升,以适应该 函数或运算符的预期类型。
  • 在参数值上调用函数或运算符。

如果这些步骤中的任何一个失败,该调用就会生成错误。错误的影响 定义于 17.2 表达式求值一节。

还存在“函数形式”,其求值规则不同于 函数,具体由每个这样的形式规定。

17.2.2 求值错误

表达式的求值可能导致 错误, 例如函数的参数是错误数据类型的字面量, 或参数是错误种类的 RDF 项时。

如果表达式的求值引发错误,则包含 该错误表达式的每个函数、运算符和表达式的 求值也会引发错误。 某些函数形式 会按其定义中的描述处理错误。

17.2.3 有效布尔值 (EBV)

有效布尔值用于计算传给逻辑函数 logical-andlogical-orlogical-not 的参数, 也用于求值 FILTER 表达式的结果。

xsd:boolean  EBV (RDF term term)
  • 如果参数是一个 literal, 其 datatype IRIxsd:boolean,且具有 有效词汇形式,则 EBV 函数返回该参数。
  • 如果参数是一个 literal, 其数据类型派生自 numeric 类型, 且该参数具有有效词汇形式, 则当操作数的值为 NaN 或数值上等于零时, EBV 函数返回字面量 "false"^^xsd:boolean; 否则 EBV 函数返回字面量 "true"^^xsd:boolean
  • 如果参数是一个 literal, 其 datatype IRIxsd:string 且值等于空字符串, 则 EBV 函数返回字面量 "false"^^xsd:boolean; 否则 EBV 函数返回字面量 "true"^^xsd:boolean
  • 如果参数是一个 literal, 并且对于其 datatype IRI 具有无效词汇形式, 则引发错误。
  • 如果参数是一个 literal, 其 datatype IRI 既不是 xsd:boolean, 也不是 numeric 数据类型, 也不是 xsd:string,则引发一个错误
  • 如果参数不是 literal, 则引发错误。
示例 EBV 值
EBV("true"^^xsd:boolean) true
EBV("") false
EBV("1"^^xsd:boolean) true
EBV(-2e10) true
EBV(-0) false
EBV(<http://example/>) error
EBV("2025-08-18"^^xsd:date) error

true 的 EBV 表示为一个 literal, 其 datatype IRI 为 xsd:boolean,词汇值为 "true"; false 的 EBV 表示为一个 literal, 其 datatype IRI 为 xsd:boolean,词汇值为 "false"。

17.3 运算符映射

SPARQL 文法标识一组用于构造约束的运算符 (例如 &&*isIRI)。 下表将每个这样的文法产生式与适当的操作数,以及由 XPath 和 XQuery 函数与运算符 3.1 [XPATH-FUNCTIONS-31] 或 第 17.4 节中指定的 SPARQL 运算符所定义的运算符函数相关联。在为给定参数集选择运算符定义时, 具有最具体参数的定义适用。例如,在求值 xsd:integer = xsd:signedInt 时,适用的是带有两个 numeric 参数的 = 定义,而不是带有两个 RDF terms 的定义。该表经过排列,使最上方可行的 候选项最具体。没有适当操作数而调用的运算符 会导致一个错误

SPARQL 遵循 XPath 对数值运算符参数进行数值类型提升和子类型替换的方案。 XPath 运算符映射 中用于 numeric 操作数(xsd:integerxsd:decimalxsd:floatxsd:double 以及派生自 numeric 类型的类型)的规则同样适用于 SPARQL 运算符(见 XML 路径语言 (XPath)3.1 [XPATH-31] 中 数值类型 提升子类型替换的定义)。 某些运算符与嵌套函数表达式相关联,例如 fn:not(op:numeric-equal(A, B))。请注意,根据 XPath 定义, 如果参数是错误,fn:notop:numeric-equal 会产生错误。

fn:compare 的排序规则由 XPath 定义,并由 http://www.w3.org/2005/xpath-functions/collation/codepoint 标识。该排序规则 允许基于码位值进行字符串比较。码位字符串等价性可以 用 RDF term 等价性来测试。

SPARQL 一元运算符
运算符 Type(A) 函数 结果类型
XQuery 一元运算符
! A xsd:boolean (EBV) logical-not(A) xsd:boolean
+ A numeric op:numeric-unary-plus(A) numeric
- A numeric op:numeric-unary-minus(A) numeric
SPARQL 二元运算符
运算符 Type(A) Type(B) 函数 结果类型
逻辑连接词
A || B xsd:boolean (EBV) xsd:boolean (EBV) logical-or(A, B) xsd:boolean
A && B xsd:boolean (EBV) xsd:boolean (EBV) logical-and(A, B) xsd:boolean
XPath 测试
A = B numeric numeric op:numeric-equal(A, B) xsd:boolean
A = B xsd:string xsd:string op:numeric-equal(fn:compare(STR(A), STR(B)), 0) xsd:boolean
A = B xsd:boolean xsd:boolean op:boolean-equal(A, B) xsd:boolean
A = B xsd:dateTime xsd:dateTime op:dateTime-equal(A, B) xsd:boolean
A != B numeric numeric fn:not(op:numeric-equal(A, B)) xsd:boolean
A != B xsd:string xsd:string fn:not(op:numeric-equal(fn:compare(STR(A), STR(B)), 0)) xsd:boolean
A != B xsd:boolean xsd:boolean fn:not(op:boolean-equal(A, B)) xsd:boolean
A != B xsd:dateTime xsd:dateTime fn:not(op:dateTime-equal(A, B)) xsd:boolean
A < B numeric numeric op:numeric-less-than(A, B) xsd:boolean
A < B xsd:string xsd:string op:numeric-equal(fn:compare(STR(A), STR(B)), -1) xsd:boolean
A < B xsd:boolean xsd:boolean op:boolean-less-than(A, B) xsd:boolean
A < B xsd:dateTime xsd:dateTime op:dateTime-less-than(A, B) xsd:boolean
A > B numeric numeric op:numeric-greater-than(A, B) xsd:boolean
A > B xsd:string xsd:string op:numeric-equal(fn:compare(STR(A), STR(B)), 1) xsd:boolean
A > B xsd:boolean xsd:boolean op:boolean-greater-than(A, B) xsd:boolean
A > B xsd:dateTime xsd:dateTime op:dateTime-greater-than(A, B) xsd:boolean
A <= B numeric numeric logical-or(op:numeric-less-than(A, B), op:numeric-equal(A, B)) xsd:boolean
A <= B xsd:string xsd:string fn:not(op:numeric-equal(fn:compare(STR(A), STR(B)), 1)) xsd:boolean
A <= B xsd:boolean xsd:boolean fn:not(op:boolean-greater-than(A, B)) xsd:boolean
A <= B xsd:dateTime xsd:dateTime fn:not(op:dateTime-greater-than(A, B)) xsd:boolean
A >= B numeric numeric logical-or(op:numeric-greater-than(A, B), op:numeric-equal(A, B)) xsd:boolean
A >= B xsd:string xsd:string fn:not(op:numeric-equal(fn:compare(STR(A), STR(B)), -1)) xsd:boolean
A >= B xsd:boolean xsd:boolean fn:not(op:boolean-less-than(A, B)) xsd:boolean
A >= B xsd:dateTime xsd:dateTime fn:not(op:dateTime-less-than(A, B)) xsd:boolean
XPath 算术
A * B numeric numeric op:numeric-multiply(A, B) numeric
A / B numeric numeric op:numeric-divide(A, B) numeric;但如果两个操作数都是 xsd:integer,则为 xsd:decimal
A + B numeric numeric op:numeric-add(A, B) numeric
A - B numeric numeric op:numeric-subtract(A, B) numeric
SPARQL 测试
A = B IRI IRI sameTerm(A, B) xsd:boolean
A = B Blank Node Blank Node sameTerm(A, B) xsd:boolean
A = B Triple Term Triple Term ( A.subject = B.subject ) &&
( A.predicate = B.predicate ) &&
( A.object = B.object )
xsd:boolean
A != B IRI IRI fn:not(sameTerm(A, B)) xsd:boolean
A != B Blank Node Blank Node fn:not(sameTerm(A, B) xsd:boolean
A != B Triple Term Triple Term ( A.subject != B.subject ) ||
( A.predicate != B.predicate ) ||
( A.object != B.object )
xsd:boolean
A = B RDF term RDF term sameValue(A, B) xsd:boolean
A != B RDF term RDF term fn:not(sameValue(A, B)) xsd:boolean

标有“(EBV)”的 xsd:boolean 函数参数, 会通过求值该参数的有效布尔值而强制转换为 xsd:boolean。

应用于 三元组项的 运算符 =!= 会把该运算符应用于各组成部分。

17.3.1 运算符可扩展性

SPARQL 语言扩展可以提供运算符与 运算符函数之间的附加关联;这相当于向上表添加行。任何附加运算符 不得产生会替换除错误以外任何结果的结果。 该规则的结果是,SPARQL FILTER 在应用 FILTER 之后会产生与未扩展实现 至少相同的中间绑定。

预期“<”运算符的附加映射用于控制操作数的相对顺序, 尤其是在 ORDER BY 子句中使用时。

17.4 函数定义

本节定义由 SPARQL 查询语言引入的运算符和函数。 示例展示这些运算符在由适当文法结构调用时的行为。

17.4.1 函数形式

17.4.1.1 BOUND
xsd:boolean  BOUND (variable var)

如果 var 被绑定到一个值,则返回 true。 否则返回 false。值为 NaN 或 INF 的变量被视为已绑定。

数据:

PREFIX foaf:        <http://xmlns.com/foaf/0.1/>
PREFIX dc:          <http://purl.org/dc/elements/1.1/>
PREFIX xsd:          <http://www.w3.org/2001/XMLSchema#>

_:a  foaf:givenName  "Alice".

_:b  foaf:givenName  "Bob" .
_:b  dc:date         "2005-04-04T04:04:04Z"^^xsd:dateTime .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc:   <http://purl.org/dc/elements/1.1/>
PREFIX xsd:   <http://www.w3.org/2001/XMLSchema#>
SELECT ?givenName
WHERE {
   ?x foaf:givenName  ?givenName .
   OPTIONAL { ?x dc:date ?date } .
   FILTER ( bound(?date) )
}

查询结果:

givenName
"Bob"

可以通过指定一个 OPTIONAL 图模式来测试某个图模式是否 被表达,该图模式引入一个变量,然后测试该变量是否未 绑定。 这在逻辑编程中称为失败即否定

此查询匹配具有 name没有表达 date 的人员:

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc:   <http://purl.org/dc/elements/1.1/>
SELECT ?name
WHERE { 
    ?x foaf:givenName  ?name .
    OPTIONAL { ?x dc:date ?date } .
    FILTER (!bound(?date))
 }

查询结果:

name
"Alice"

由于 Bob 的 dc:date 是已知的,"Bob" 不是该查询的解。

17.4.1.2 IF
rdfTerm  IF (expression1, expression2, expression3)

IF 函数形式对第一个参数求值,将其解释为 有效布尔值,然后如果 EBV 为 true,则返回 expression2 的值;否则返回 expression3 的值。expression2expression3 中只有一个会被求值。如果对第一个参数求值引发错误, 则对 IF 表达式求值会引发一个错误

示例:假设在某个查询解中,?x 绑定到 2?z 绑定到 0, 并且 ?y 未绑定:

IF(?x = 2, "yes", "no") 返回 "yes"
IF(bound(?y), "yes", "no") 返回 "no"
IF(?x=2, "yes", 1/?z) 返回 "yes",表达式 1/?z 不会被求值
IF(?x=1, "yes", 1/?z) 引发错误
IF("2" > 1, "yes", "no") 引发错误
17.4.1.3 COALESCE
rdfTerm COALESCE(expression, ....)

COALESCE 函数形式返回第一个求值不产生错误的 表达式的 RDF 项值。 在 SPARQL 中,对未绑定变量求值会引发错误。

如果没有任何表达式求值时不产生错误,则引发错误。

如果表达式数量为零,则引发错误。

示例:假设在某个查询解中 ?x = 2 且 ?y 未绑定:

COALESCE(?x, 1/0) 返回 2,即 x 的值
COALESCE(1/0, ?x) 返回 2
COALESCE(5, ?x) 返回 5
COALESCE(?y, 3) 返回 3
COALESCE(?y) 引发错误,因为 y 未绑定。
COALESCE() 引发错误,因为参数数量为零。
17.4.1.4 NOT EXISTS 与 EXISTS

有一个过滤器运算符 EXISTS,它接受一个图模式。 EXISTS 返回 truefalse, 具体取决于该模式与解映射一起是否匹配数据集。 不会发生变量的额外绑定。NOT EXISTS 形式 会转换为 fn:not(EXISTS {...})

xsd:boolean  NOT EXISTS { pattern }

如果 pattern 匹配,则返回 false。 否则返回 true

NOT EXISTS { pattern } 等价于 fn:not(EXISTS { pattern })

xsd:boolean EXISTS { pattern }

如果 pattern 匹配,则返回 true。 否则返回 false

形式上,对于每个形式为 EXISTS { pattern }表达式 expr, 相对于解映射 μ、 在具有活动图 G数据集 D上下文中 求值 expr 的结果为:

  • 如果 eval(D(G), A, μ) 非空,则为 "true"^^xsd:boolean
  • 如果 eval(D(G), A, μ) 为空,则为 "false"^^xsd:boolean

其中 A 是按照18.3 到代数 语法的转换,通过转换 { pattern } 获得的 代数查询表达式

按照文法中的 ExistsFunc 产生式, { pattern } 匹配 GroupGraphPattern 产生式。 18.3 到代数语法的转换中涵盖任何 GroupGraphPattern 转换的具体小节 是18.3.2.6 转换图模式

17.4.1.5 logical-or
xsd:boolean logical-or (xsd:boolean left, xsd:boolean right)

此函数不能在表达式中直接使用。 此函数的目的是定义“||”运算符的语义。

该函数返回 leftright 的逻辑 OR。请注意,logical-or 作用于其每个参数的有效布尔值

注:关于 || 运算符如何处理错误,见 17.2 表达式求值一节。

17.4.1.6 logical-and
xsd:boolean logical-and (xsd:boolean left, xsd:boolean right)

此函数不能在表达式中直接使用。 此函数的目的是定义“&&” 运算符的语义。

该函数返回 leftright 的逻辑 AND。请注意,logical-and 作用于其每个参数的有效布尔值

注:关于 && 运算符如何处理错误,见 17.2 表达式求值一节。

17.4.1.7 logical-not
xsd:boolean logical-not (xsd:boolean arg)

此函数不能在表达式中直接使用。此函数的目的是 定义“!”运算符的语义。

该函数返回 arg 的逻辑 NOT。 请注意,logical-not 作用于其 参数的有效布尔值

17.4.1.8 IN
boolean  rdfTerm IN (expression, ...)

IN 运算符测试左侧的 RDF 项是否出现在 右侧表达式值的列表中。该测试使用 “=” 运算符完成, 后者按照运算符映射所确定的方式 测试是否为同一值。

右侧含有零个项的列表是合法的,并且求值为 false

比较中的错误会导致 IN 表达式 引发错误,前提是正在测试的 RDF 项未在该项列表的 其他位置找到。

如果 IN 与一个表达式一起用于产生 rdfTerm,则该表达式只会在求值 IN 表达式之前求值一次。

IN 运算符等价于以下 SPARQL 表达式:

(rdfTerm = value of expression1) || (rdfTerm = value of expression2) || ...

示例:

2 IN (1, 2, 3) true
2 IN () false
2 IN (<http://example/iri>, "str", 2.0) true
2 IN (1/0, 2) true
2 IN (2, 1/0) true
2 IN (3, 1/0) 引发错误
17.4.1.9 NOT IN
boolean  rdfTerm NOT IN (expression, ...)

NOT IN 运算符测试左侧的 RDF 项是否 未出现在右侧表达式列表的值中。该测试使用 “!=” 运算符完成,后者按照 运算符映射所确定的方式 测试两个值是否不是同一值。

右侧含有零个项的列表是合法的,并且求值为 true

如果 NOT IN 与一个表达式一起用于产生 rdfTerm,则该表达式只会在求值 NOT IN 表达式之前求值一次。

比较中的错误会导致 NOT IN 表达式引发错误,前提是 正在测试的 RDF 项未在该项列表的其他位置找到。

NOT IN 运算符等价于以下 SPARQL 表达式:

(rdfTerm != value of expression1) && (rdfTerm != value of expression2) && ...

NOT IN (...) 等价于 !(IN (...))

示例:

2 NOT IN (1, 2, 3) false
2 NOT IN () true
2 NOT IN (<http://example/iri>, "str", 2.0) false
2 NOT IN (1/0, 2) false
2 NOT IN (2, 1/0) false
2 NOT IN (3, 1/0) 引发错误

17.4.2 RDF 项上的函数

17.4.2.1 sameTerm
xsd:boolean  sameTerm (RDF term term1, RDF term term2)

如果 term1term2RDF 1.2 概念与抽象数据 模型 [RDF12-CONCEPTS] 中定义的同一 RDF 项,则返回 TRUE;否则返回 FALSE。

如果以下任一条件为 true,则 term1term2同一 RDF 项

sameTerm(<http://example/>, <http://example/>) true
sameTerm(<http://example/>, <https://example/>) false
sameTerm("abc", "abc") true
sameTerm("abc"@en, "abc") false
sameTerm("abc"@en, "abc"@EN) true
sameTerm("abc"@en--rtl, "abc"@en) false
sameTerm(2, 2.0) false
sameTerm(2, "2"^^xsd:integer) true
sameTerm(2, "02"^^xsd:integer) false
17.4.2.2 sameValue

此函数取代 SPARQL 1.1 中的 RDFterm-equal

xsd:boolean sameValue (RDF term term1, RDF term term2)

此函数不能在表达式中直接使用。此函数的目的是 在 “=” 运算符应用于两个 RDF 项,且它们不属于 17.3 运算符 映射一节中运算符映射表所涵盖的具体情形时, 定义该运算符的语义。

此函数的结果通过执行以下步骤确定。

  1. 如果 term1term2相等的 RDF 项, 则返回 TRUE。
  2. 如果 term1term2IRIblank node, 则返回 FALSE。
  3. 如果 term1term2 中恰好一个是 triple term, 则返回 FALSE。
  4. 如果 term1term2 都是 triple terms, 则将 sameValue 函数两两应用于每个组成部分。 如果每个组成部分对都返回 TRUE,则返回 TRUE; 如果任何组成部分对产生错误, 则产生一个错误; 否则返回 FALSE。
  5. 如果 term1term2 都是 literals, 且其中一个或两个字面量已知为 病态类型, 则产生一个错误
  6. "NaN"^^xsd:double"NaN"^^xsd:float 被视为 表示同一值。 如果 term1term2 对于 xsd:double 或 xsd:float 均为 "NaN",则返回 TRUE。
  7. 如果 term1term2 都是 literals, 且 SPARQL 处理器能够确定它们的值相等, 则返回 TRUE。
  8. 如果 term1term2 都是 literals, 且 SPARQL 处理器能够确定它们的值 不相等,则返回 FALSE。
  9. 否则,产生一个错误

如果两个参数都是字面量,则在 SPARQL 处理器能够确定 这些字面量的值相等或不相等的情况下,函数 sameValue 返回 truefalse。 如果 SPARQL 处理器无法确定,则返回 error

如果一个字面量的数据类型由 SPARQL 处理器处理,且其词汇形式不在该数据类型的 词汇空间 中,则该字面量为 病态类型

对于 xsd:double 和 xsd:float,+0-00 是同一 值。

=”的运算符映射 是函数 op:numeric-equal, 其定义是在比较涉及 NaN 的参数时返回 false。 然而,sameTerm("NaN"^^xsd:double, "NaN"^^xsd:double) 为 true。 函数 sameValuesameValue("NaN"^^xsd:double, "NaN"^^xsd:double) 定义为 true,因为这些参数是值空间中的同一元素。 类似地,函数 sameValuesameValue("NaN"^^xsd:float, "NaN"^^xsd:float) 定义为 true。

sameValue"NaN"^^xsd:double"NaN"^^xsd:float 的值视为同一值。 sameValue("NaN"^^xsd:double, "NaN"^^xsd:float)sameValue("NaN"^^xsd:float, "NaN"^^xsd:double) 都为 true

示例:

sameValue 结果
sameValue(1e10, "NaN"^^xsd:double) false
sameValue("NaN"^^xsd:double, "NaN"^^xsd:double) true
sameValue("NaN"^^xsd:double, "NaN"^^xsd:float) true
sameValue( <<(:s :p 123)>> , <<(:s :p 123.0)>> ) true

扩展实现可以支持字面量的附加数据类型。处理一个查询的实现, 在测试具有未识别数据类型(且词汇形式和 datatype IRI 不相同)的字面量是否等价时,会返回错误,表示它无法确定 被比较字面量的值是否等价。例如,未扩展的实现 在测试 "iiii"^^my:romanNumeral = "iv"^^my:romanNumeral 时会产生错误。

17.4.2.3 isIRI
xsd:boolean  isIRI (RDF term term)
xsd:boolean  isURI (RDF term term)

如果 term 是一个 IRI,则返回 true。 否则返回 falseisURIisIRI 运算符的另一种拼写。

PREFIX foaf:       <http://xmlns.com/foaf/0.1/>

_:a  foaf:name       "Alice".
_:a  foaf:mbox       <mailto:alice@work.example> .

_:b  foaf:name       "Bob" .
_:b  foaf:mbox       "bob@work.example" .

此查询匹配具有 namemboxmbox 是 IRI 的人员:

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE {
    ?x foaf:name  ?name ;
       foaf:mbox  ?mbox .
    FILTER isIRI(?mbox) 
}

查询结果:

name mbox
"Alice" <mailto:alice@work.example>
17.4.2.4 isBLANK
xsd:boolean  isBLANK (RDF term term)

如果 term 是一个 blank node,则返回 true。否则返回 false

PREFIX a:          <http://www.w3.org/2000/10/annotation-ns#>
PREFIX dc:         <http://purl.org/dc/elements/1.1/>
PREFIX foaf:       <http://xmlns.com/foaf/0.1/>

_:a   a:annotates   <http://www.w3.org/TR/rdf-sparql-query/> .
_:a   dc:creator    "Alice B. Toeclips" .

_:b   a:annotates   <http://www.w3.org/TR/rdf-sparql-query/> .
_:b   dc:creator    _:c .
_:c   foaf:given    "Bob".
_:c   foaf:family   "Smith".

此查询匹配其 dc:creator 使用来自 FOAF 词汇表的谓词来表达 姓名的人员。

PREFIX a:      <http://www.w3.org/2000/10/annotation-ns#>
PREFIX dc:     <http://purl.org/dc/elements/1.1/>
PREFIX foaf:   <http://xmlns.com/foaf/0.1/>

SELECT ?given ?family
WHERE { 
    ?annot  a:annotates  <http://www.w3.org/TR/rdf-sparql-query/> .
    ?annot  dc:creator   ?c .
    OPTIONAL { ?c  foaf:given   ?given ; foaf:family  ?family } .
    FILTER isBLANK(?c)
}

查询结果:

given family
"Bob" "Smith"

在此示例中,dc:creator 谓词有两个宾语,但 只有一个(_:c)是空白节点。

17.4.2.5 isLITERAL
xsd:boolean  isLITERAL (RDF term term)

如果 term 是一个 literal,则返回 true。否则返回 false

PREFIX foaf:       <http://xmlns.com/foaf/0.1/>
                
_:a  foaf:name       "Alice".
_:a  foaf:mbox       <mailto:alice@work.example> .

_:b  foaf:name       "Bob" .
_:b  foaf:mbox       "bob@work.example" .

此查询类似于 17.4.2.1 中的查询, 但它匹配具有 namemboxmbox 是字面量的人员。这可用于查找错误数据 (foaf:mbox 应该只把 IRI 作为其宾语)。

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE {
    ?x foaf:name  ?name ;
       foaf:mbox  ?mbox .
    FILTER isLiteral(?mbox)
}

查询结果:

name mbox
"Bob" "bob@work.example"
17.4.2.6 isNUMERIC
xsd:boolean  isNUMERIC (RDF term term)

如果 term 是数值,则返回 true。 否则返回 false。如果 term 具有适当的数据类型 (见操作数数据类型一节)并且具有 有效词汇形式,使其成为接受数值参数的函数和运算符的有效参数, 则 term 是数值。

示例:

isNUMERIC(12) true
isNUMERIC("12") false
isNUMERIC("12"^^xsd:nonNegativeInteger) true
isNUMERIC("1200"^^xsd:byte) false
isNUMERIC(<http://example/>) false
17.4.2.7 STR
xsd:string  STR (literal literal)
xsd:string  STR (IRI rsrc)

返回 literal(一个 literal)的 词汇形式;返回 rsrc(一个 IRI)的码位表示。这有助于检查 IRI 的各个部分,例如主机名。

PREFIX foaf:       <http://xmlns.com/foaf/0.1/>

_:a  foaf:name       "Alice".
_:a  foaf:mbox       <mailto:alice@work.example> .

_:b  foaf:name       "Bob" .
_:b  foaf:mbox       <mailto:bob@home.example> .

此查询选择在其 foaf 资料中使用 work.example 地址的人员集合:

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE {
    ?x foaf:name  ?name ;
      foaf:mbox  ?mbox .
    FILTER regex(str(?mbox), "@work\\.example$")
}

查询结果:

name mbox
"Alice" <mailto:alice@work.example>
17.4.2.8 LANG
xsd:string  LANG (literal ltrl)

如果 ltrl 具有 语言标签, 则返回它的语言标签。 如果 ltrl 没有 语言标签, 则返回空字符串。 请注意,RDF 数据模型不包含具有空 语言标签的字面量。

PREFIX foaf:       <http://xmlns.com/foaf/0.1/>

_:a  foaf:name       "Robert"@en.
_:a  foaf:name       "Roberto"@es.
_:a  foaf:mbox       <mailto:bob@work.example> .

此查询查找西班牙语 foaf:namefoaf:mbox

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE {
    ?x foaf:name  ?name ;
       foaf:mbox  ?mbox .
    FILTER ( lang(?name) = "es" )
}

查询结果:

name mbox
"Roberto"@es <mailto:bob@work.example>

函数示例:

表达式 结果
LANG("abc"@en) "en"
LANG("abc"@en--ltr) "en"
LANG("abc") ""
LANG(1) ""
LANG(<http://example/>) error
17.4.2.9 LANGDIR
xsd:string  LANGDIR (literal ltrl)

如果 ltrl 具有 基方向, 则返回它的基方向。 如果 ltrl 没有 基方向, 则返回空字符串。 请注意,RDF 数据模型不包含具有空 基方向的字面量。

表达式 结果
LANGDIR("abc"@en--ltr) "ltr"
LANGDIR("abc"@en) ""
LANGDIR("abc") ""
LANGDIR(1) ""
LANGDIR(<http://example/>) error
17.4.2.10 hasLANG
xsd:string  hasLANG (RDF term term)

如果 RDF 项参数是带有 语言标签的字面量, 则返回 true。 否则,该函数返回 false

如果参数是字面量,则该函数等价于 测试该字面量的数据类型是否为 rdf:langStringrdf:dirLangString

表达式 结果
hasLANG("abc"@en) true
hasLANG("abc@"en--ltr) true
hasLANG("تصميم المواقع"@ar--rtl) true
hasLANG(1) false
hasLANG(<http://example/>) false
17.4.2.11 hasLANGDIR
xsd:string  hasLANGDIR (RDF term term)

如果 RDF 项参数是带有 基方向的字面量, 则返回 true。 否则,该函数返回 false

如果参数是字面量,则该函数等价于 测试该字面量的数据类型是否为 rdf:dirLangString

表达式 结果
hasLANGDIR("abc"@en) false
hasLANGDIR("abc@"en--ltr) true
hasLANGDIR("تصميم المواقع"@ar--rtl) true
hasLANGDIR(1) false
hasLANGDIR(<http://example/>) false
17.4.2.12 DATATYPE
iri  DATATYPE (literal literal)

返回给定字面量的 datatype IRI

具有 语言标签没有 基方向的字面量的 datatype IRIrdf:langString

具有 语言标签基方向 的字面量的 datatype IRIrdf:dirLangString

PREFIX foaf:       <http://xmlns.com/foaf/0.1/>
PREFIX eg:         <http://biometrics.example/ns#>
PREFIX xsd:        <http://www.w3.org/2001/XMLSchema#>

_:a  foaf:name       "Alice".
_:a  eg:shoeSize     "9.5"^^xsd:float .

_:b  foaf:name       "Bob".
_:b  eg:shoeSize     "42"^^xsd:integer .

此查询查找所有 shoeSize 为整数的人员的 foaf:namefoaf:shoeSize

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>
PREFIX eg:   <http://biometrics.example/ns#>
SELECT ?name ?shoeSize
WHERE { 
    ?x foaf:name  ?name ;
       eg:shoeSize  ?shoeSize .
    FILTER ( datatype(?shoeSize) = xsd:integer )
}

查询结果:

name shoeSize
"Bob" 42
17.4.2.13 IRI
iri  IRI(xsd:string)
iri  IRI(iri)
iri  URI(xsd:string)
iri  URI(iri)

IRI 函数通过解析字符串参数来构造 IRI(见 [RFC3986] 和 [RFC3987],或任何取代 RFC 3986 或 RFC 3987 的后续 RFC)。该 IRI 会相对于查询的基 IRI 解析,并且必须得到一个绝对 IRI。

URI 函数是 IRI 的同义词。

如果传给该函数的是 IRI,则它原样返回该 IRI。

传入除数据类型为 xsd:string 的字面量或 IRI 之外的任何 RDF 项,都是 错误。

实现可以规范化该 IRI。

示例:

IRI("http://example/") <http://example/>
IRI(<http://example/>) <http://example/>
17.4.2.14 BNODE
blank node  BNODE()
blank node  BNODE(xsd:string)

BNODE 函数构造一个空白节点,它不同于 被查询数据集中的所有空白节点,也不同于为其他查询解调用 此构造器所创建的所有空白节点。如果使用无参数形式, 每次调用都会产生一个不同的空白节点。如果使用带有 xsd:string 字面量的形式, 则对于不同的 xsd:string 字面量,每次调用都会产生不同的空白节点;而在一个 解映射的表达式中, 使用相同 xsd:string 字面量调用时会得到同一个空白节点。

此功能与 SPARQL CONSTRUCT 模板中对 空白节点的处理兼容。

17.4.2.15 STRDT
literal  STRDT(xsd:string lexicalForm, IRI datatypeIRI)

STRDT 函数按照参数所指定的 词汇形式datatype IRI 构造一个字面量。

表达式 结果
STRDT("123", xsd:integer) "123"^^<http://www.w3.org/2001/XMLSchema#integer>
STRDT("iiii", <http://example/romanNumeral>) "iiii"^^<http://example/romanNumeral>
不应使用 datatypeIRI 参数 rdf:langStringrdf:dirLangString 调用 STRDT。若要创建以这些 IRI 作为 datatype IRI 的字面量, 应使用函数 STRLANGSTRLANGDIR
17.4.2.16 STRLANG
literal  STRLANG(xsd:string lexicalForm, xsd:string langTag)

STRLANG 函数按照参数所指定的 词汇形式语言标签 构造一个字面量, 并带有 rdf:langString 的 datatype IRI。

参数 langTag 不得为空字符串,并且应该是 有效的语言标签

表达式 结果
STRLANG("chat", "fr") "chat"@fr
STRLANG("abc", "") error
STRLANG(123, "en") error
17.4.2.17 STRLANGDIR
literal  STRLANGDIR(xsd:string lexicalForm, xsd:string langTag, xsd:string baseDirection)

STRLANGDIR 函数按照参数所指定的 词汇形式语言标签基方向 构造一个字面量, 并带有 rdf:dirLangString 的 datatype IRI。

参数 langTag 不得为空字符串,并且应该是 有效的语言标签。 参数 baseDirection 必须"ltr""rtl"

表达式 结果
STRLANGDIR("abc", "en", "ltr") "abc"@en--ltr
STRLANGDIR("abc", "en", "LTR") error
STRLANGDIR("قطة", "ar", "rtl") "قطة"@ar--rlt
STRLANGDIR("abc", "en", "") error
STRLANGDIR("abc", "", "ltr") error
STRLANGDIR(123, "", "ltr") error
STRLANGDIR(<x:uri>, "en", "ltr") error
17.4.2.18 UUID
iri  UUID()

返回来自 通用唯一标识符(UUID)URN 命名空间的全新 IRI。每次调用 UUID() 都会返回一个 不同的 UUID。它不得是 “nil” UUID(全为零)。UUID 的变体和版本 由实现决定。

UUID() <urn:uuid:b9302fb5-642e-4d3b-af19-29a8f6d894c9>
17.4.2.19 STRUUID
xsd:string  STRUUID()

返回一个字符串,即 UUID 的方案特定部分。也就是说,它作为数据类型 为 xsd:string 的字面量,是生成 UUID、转换为数据类型为 xsd:string 的字面量并移除起始 urn:uuid: 之后的结果。

STRUUID() "73cd4307-8a99-4691-a608-b5bda64fb6c1"

17.4.3 字符串上的函数

某些函数(例如 REGEXSTRLENCONTAINS) 以字符串字面量作为参数。 字符串字面量是以下之一:

  • 数据类型为 xsd:string 的字面量
  • 数据类型为 rdf:langString 且带有 语言标签的字面量
  • 数据类型为 rdf:dirLangString 且同时带有 语言标签基方向的字面量

使用任何其他 RDF 项都会导致对该函数的调用引发错误。

"abc"简单字面量 的语法缩写,表示 "abc"^^xsd:string

函数 SUBSTRSTRBEFORESTRAFTERREPLACE 返回与其第一个参数 同种类的字符串字面量

函数 CONCAT 根据参数的 字符串字面量形式返回一个字符串 字面量

函数 STRSTARTSSTRENDSCONTAINSSTRBEFORESTRAFTER 接受两个参数。这些参数必须参数兼容; 否则,调用该函数会引发错误。

如果满足以下条件,则两个字符串字面量参数是 参数 兼容的:

  • 参数是数据类型为 xsd:string 的字面量
  • 参数是数据类型为 rdf:langString 的字面量, 并具有相同的语言标签
  • 参数是数据类型为 rdf:dirLangString 的字面量, 并具有相同的 语言标签 和相同的基方向
  • 第一个参数是数据类型为 rdf:langString 的字面量, 第二个参数是数据类型为 xsd:string 的字面量
  • 第一个参数是数据类型为 rdf:dirLangString 的字面量, 第二个参数具有数据类型 xsd:string
Argument1 Argument2 兼容?
"abc" "b"
"abc"@en "b"
"abc"@en "b"@en
"abc"@fr "b"@ja
"abc" "b"@ja
"abc" "b"@en--ltr
"abc"@en--ltr "b"@en--ltr
"abc"@en--ltr "b"@en
"abc"@en--ltr "z"
17.4.3.1 STRLEN
xsd:integer  STRLEN(string literal str)

strlen 函数对应于 XPath fn:string-length 函数,并返回一个 xsd:integer,其值等于该字面量 词汇形式的字符长度。

strlen("chat") 4
strlen("chat"@en) 4
strlen("chat"@en--ltr) 4
strlen("chat"^^xsd:string) 4
17.4.3.2 SUBSTR
string literal  SUBSTR(string literal source, xsd:integer startingLoc)
string literal  SUBSTR(string literal source, xsd:integer startingLoc, xsd:integer length)

substr 函数对应于 XPath fn:substring 函数,并返回一个与 source 输入参数同种类的字面量 (数据类型为 xsd:string 的字面量、带有相同语言标签的字面量、 带有相同语言标签和基方向的字面量),但其 词汇形式 派生自源的词汇形式的子字符串。

参数 startingLoclength 可以是 xsd:integer 的派生类型。

字符串中第一个字符的索引是 1。

substr("foobar", 4) "bar"
substr("foobar"@en, 4) "bar"@en
substr("foobar"^^xsd:string, 4) "bar"^^xsd:string
substr("foobar", 4, 1) "b"
substr("foobar"@en, 4, 1) "b"@en
substr("foobar"^^xsd:string, 4, 1) "b"^^xsd:string
17.4.3.3 UCASE
string literal  UCASE(string literal str)

UCASE 函数对应于 XPath fn:upper-case 函数。它返回一个字符串字面量, 其词汇形式是参数词汇形式的大写形式。

ucase("foo") "FOO"
ucase("Foo"@en) "FOO"@en
ucase("foo"@en--ltr) "FOO"@en--ltr
ucase("foo"^^xsd:string) "FOO"^^xsd:string
17.4.3.4 LCASE
string literal  LCASE(string literal str)

LCASE 函数对应于 XPath fn:lower-case 函数。 它返回一个字符串字面量,其词汇形式是参数词汇形式的小写形式。

lcase("BAR") "bar"
lcase("Bar"@en) "bar"@en
lcase("BAR"@en--ltr) "bar"@en--ltr
lcase("BAR"^^xsd:string) "bar"^^xsd:string
17.4.3.5 STRSTARTS
xsd:boolean  STRSTARTS(string literal arg1, string literal arg2)

STRSTARTS 函数对应于 XPath fn:starts-with 函数。 参数必须参数兼容, 否则会引发错误。

对于这样的输入对,如果 arg1 的词汇形式 以 arg2 的词汇形式开头,则函数返回 true;否则返回 false。

strStarts("foobar", "foo") true
strStarts("foobar", "abc") false
strStarts("foobar"@en, "foo"@en) true
strStarts("foobar"^^xsd:string, "foo"^^xsd:string) true
strStarts("foobar"^^xsd:string, "foo") true
strStarts("foobar", "foo"^^xsd:string) true
strStarts("foobar"@en, "foo") true
strStarts("foobar"@en, "foo"^^xsd:string) true
strStarts("foobar", "foo"@en) error
17.4.3.6 STRENDS
xsd:boolean  STRENDS(string literal arg1, string literal arg2)

STRENDS 函数对应于 XPath fn:ends-with 函数。 参数必须参数兼容, 否则会引发错误。

对于这样的输入对,如果 arg1 的词汇形式 以 arg2 的词汇形式结尾,则函数返回 true;否则返回 false。

strEnds("foobar", "bar") true
strEnds("foobar", "abc") false
strEnds("foobar"@en, "bar"@en) true
strEnds("foobar"^^xsd:string, "bar"^^xsd:string) true
strEnds("foobar"^^xsd:string, "bar") true
strEnds("foobar", "bar"^^xsd:string) true
strEnds("foobar"@en, "bar") true
strEnds("foobar"@en, "bar"^^xsd:string) true
strEnds("foobar"@en, "bar"@en) error
17.4.3.7 CONTAINS
xsd:boolean  CONTAINS(string literal arg1, string literal arg2)

CONTAINS 函数对应于 XPath fn:contains。 参数必须参数兼容, 否则会引发错误。

contains("foobar", "bar") true
contains("foobar"@en, "foo"@en) true
contains("foobar"^^xsd:string, "bar"^^xsd:string) true
contains("foobar"^^xsd:string, "foo") true
contains("foobar", "bar"^^xsd:string) true
contains("foobar"@en, "foo") true
contains("foobar"@en, "bar"^^xsd:string) true
contains("foobar", "bar"@en) error
17.4.3.8 STRBEFORE
literal  STRBEFORE(string literal arg1, string literal arg2)

STRBEFORE 函数对应于 XPath fn:substring-before 函数。 参数必须参数兼容, 否则会引发错误。

对于兼容参数,如果第二个参数的词汇部分作为子字符串出现在 第一个参数的词汇部分中,则该函数返回一个与第一个参数 arg1 同种类的字面量(数据类型为 xsd:string 的字面量、带有相同语言标签的字面量)。 结果的词汇形式是 arg1 的词汇形式中, 位于 arg2 词汇形式第一次出现之前的子字符串。 如果 arg2 的词汇形式为空字符串,则认为这是匹配, 结果的词汇形式为空字符串。

如果没有这样的出现,则返回一个数据类型为 xsd:string 的 空字面量。

strBefore("abc","b") "a"
strBefore("abc"@en,"bc") "a"@en
strBefore("abc"@en,"b"@cy) error
strBefore("abc"^^xsd:string,"") ""^^xsd:string
strBefore("abc","xyz") ""
strBefore("abc"@en, "z"@en) ""
strBefore("abc"@en, "z") ""
strBefore("abc"@en, ""@en) ""@en
strBefore("abc"@en, "") ""@en
17.4.3.9 STRAFTER
literal  STRAFTER(string literal arg1, string literal arg2)

STRAFTER 函数对应于 XPath fn:substring-after 函数。 参数必须参数兼容, 否则会引发错误。

对于兼容参数,如果第二个参数的词汇部分作为子字符串出现在 第一个参数的词汇部分中,则该函数返回一个与第一个参数 arg1 同种类的字面量(数据类型为 xsd:string 的字面量、带有相同语言标签的字面量)。 结果的词汇形式是 arg1 的词汇形式中, 位于 arg2 词汇形式第一次出现之后的子字符串。 如果 arg2 的词汇形式为空字符串,则认为这是匹配, 结果的词汇形式为 arg1 的词汇形式。

如果没有这样的出现,则返回一个数据类型为 xsd:string 的 空字面量。

strAfter("abc","b") `"c"
strAfter("abc"@en,"ab") "c"@en
strAfter("abc"@en,"b"@cy) error
strAfter("abc"^^xsd:string,"") "abc"^^xsd:string
strAfter("abc","xyz") ""
strAfter("abc"@en, "z"@en) ""
strAfter("abc"@en, "z") ""
strAfter("abc"@en, ""@en) "abc"@en
strAfter("abc"@en, "") "abc"@en
17.4.3.10 CONCAT
string literal  CONCAT(string literal, ..., string literal)

CONCAT 函数接受零个或多个参数。 参数必须是字符串字面量,否则会 引发错误。

如果给出零个参数,则结果是数据类型为 xsd:string 的空字符串。

如果给出一个参数,则结果是该参数值。

如果给出两个或更多参数,则该函数返回一个 字符串字面量,使得所得 词汇形式 通过使用 fn:concat 函数连接该函数参数的 词汇形式而得到。

  • 如果所有输入字面量都是具有相同 语言标签 和相同 基方向的字面量, 则返回的字符串字面量是一个 具有数据类型 rdf:dirLangString、共同语言标签和基方向的字面量。
  • 如果所有输入字面量都是具有相同 语言标签 且没有任何参数具有 基方向的字面量, 则返回的字符串字面量是一个 具有数据类型 rdf:langString 和共同语言标签的字面量。
  • 否则,结果是数据类型为 xsd:string字符串字面量
concat("foo", "bar") "foobar"
concat("foo"@en, "bar"@en) "foobar"@en
concat("foo", "bar") "foobar"
concat("foo"@en, "bar") "foobar"
concat("foo"@en, "bar"@es) "foobar"
concat("abc") "abc"
concat("abc"@en) "abc"@en
concat() ""
17.4.3.11 langMATCHES
xsd:boolean  langMatches (xsd:string language-tag, xsd:string language-range)

如果参数 language-tag (一个语言标签) 按照 [RFC4647] 第 3.3.1 节中定义的基本过滤方案, 匹配参数 language-range (按照 [RFC4647] 第 2.1 节 语言 标签匹配基本语言范围), 则返回 true。否则,该函数返回 false

如果 language-taglanguage-range 或二者为空 (因而分别不是有效的语言标签或语言范围), 则该函数返回 false

language-range 为 "*" 时匹配任何非空的 language-tag 字符串。

PREFIX dc:       <http://purl.org/dc/elements/1.1/>

_:a  dc:title         "That Seventies Show"@en .
_:a  dc:title         "Cette Série des Années Soixante-dix"@fr .
_:a  dc:title         "Cette Série des Années Septante"@fr-BE .
_:b  dc:title         "Il Buono, il Bruto, il Cattivo" .

此查询使用 langMatcheslang 来查找英文名为 "That Seventies Show" 的节目的法语标题:

PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT ?title
WHERE {
    ?x dc:title  "That Seventies Show"@en ;
       dc:title  ?title .
    FILTER langMatches( lang(?title), "FR" )
}

查询结果:

title
"Cette Série des Années Soixante-dix"@fr
"Cette Série des Années Septante"@fr-BE

惯用形式 langMatches( lang( ?v ), "*" ) 不会匹配 没有语言标签的字面量,因为 lang( ?v ) 会返回空字符串,因此

PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT ?title
WHERE {
    ?x dc:title  ?title .
    FILTER langMatches( lang(?title), "*" )
}

会报告所有带有语言标签的标题:

title
"That Seventies Show"@en
"Cette Série des Années Soixante-dix"@fr
"Cette Série des Années Septante"@fr-BE
17.4.3.12 REGEX
xsd:boolean  REGEX (string literal text, xsd:string pattern)
xsd:boolean  REGEX (string literal text, xsd:string pattern, xsd:string flags)

调用 XPath fn:matches 函数,以将 text 与正则表达式 pattern 进行匹配。正则 表达式语言定义于 XQuery 1.0 and XPath 2.0 Functions and Operators 第 7.6.1 正则 表达式语法节 [XPATH-FUNCTIONS-31]。

PREFIX foaf:       <http://xmlns.com/foaf/0.1/>

_:a  foaf:name       "Alice".
_:b  foaf:name       "Bob" .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE { 
    ?x foaf:name  ?name
    FILTER regex(?name, "^ali", "i")
}

查询结果:

name
"Alice"
17.4.3.13 REPLACE
string literal  REPLACE (string literal arg, xsd:string pattern, xsd:string replacement )
string literal  REPLACE (string literal arg, xsd:string pattern, xsd:string replacement,  xsd:string flags)

REPLACE 函数对应于 XPath fn:replace 函数。它把正则表达式 pattern 的每个非重叠出现替换为替换字符串。 正则表达式匹配可能涉及修饰符标志。见 REGEX

replace("abcd", "b", "Z") "aZcd"
replace("abab", "B", "Z","i") "aZaZ"
replace("abab", "B.", "Z","i") "aZb"
17.4.3.14 ENCODE_FOR_URI
xsd:string  ENCODE_FOR_URI(string literal ltrl)

ENCODE_FOR_URI 函数对应于 XPath fn:encode-for-uri 函数。它返回一个 数据类型为 xsd:string 的字面量,其词汇形式是根据 fn:encode-for-uri 函数转换保留字符后,从输入的词汇形式得到的。

encode_for_uri("Los Angeles") "Los%20Angeles"
encode_for_uri("Los Angeles"@en) "Los%20Angeles"
encode_for_uri("Los Angeles"^^xsd:string) "Los%20Angeles"

17.4.4 数值上的函数

17.4.4.1 ABS
numeric  ABS (numeric term)

返回 arg 的绝对值。如果 arg 不是数值,则引发错误。

对于具有来自 XDM 的数据类型的项, 此函数与 fn:abs 相同。

ABS(1) 1
ABS(-1.5) 1.5
17.4.4.2 ROUND
numeric  ROUND (numeric term)

返回最接近该参数且不含小数部分的数字。如果有两个这样的数字, 则返回最接近正无穷的那个。如果 arg 不是数值, 则引发错误。

对于具有来自 XDM 的数据类型的项,此函数与 fn:round 相同。

ROUND(2.4999) 2.0
ROUND(2.5) 3.0
ROUND(-2.5) -2.0
17.4.4.3 CEIL
numeric  CEIL (numeric term)

返回不小于 arg 值且没有小数部分的最小 (最接近负无穷的)数字。如果 arg 不是数值,则引发错误。

对于具有来自 XDM 的数据类型的项, 此函数与 fn:ceiling 相同。

CEIL(10.5) 11.0
CEIL(-10.5) -10.0
17.4.4.4 FLOOR
numeric  FLOOR (numeric term)

返回不大于 arg 值且没有小数部分的最大 (最接近正无穷的)数字。如果 arg 不是数值,则引发错误。

对于具有来自 XDM 的数据类型的项, 此函数与 fn:floor 相同。

FLOOR(10.5) 10.0
FLOOR(-10.5) -11.0
17.4.4.5 RAND
xsd:double  RAND ( )

返回一个介于 0(含)和 1.0e0(不含)之间的伪随机数。 每次调用此函数都可能产生不同的数字。数字应以近似相等的概率产生。

rand() "0.31221030831984886"^^xsd:double

17.4.5 日期和时间上的函数

17.4.5.1 NOW
xsd:dateTime  NOW ()

返回当前查询执行的 XSD dateTime 值。在任一次查询执行中, 对此函数的所有调用都必须返回相同的值。返回的确切时刻未指定。

NOW() "2011-01-10T14:45:13.815-05:00"^^xsd:dateTime
17.4.5.2 YEAR
xsd:integer  YEAR (xsd:dateTime arg)

以整数形式返回 arg 的年份部分。

此函数对应于 fn:year-from-dateTime

YEAR("2011-01-10T14:45:13.815-05:00"^^xsd:dateTime) 2011
17.4.5.3 MONTH
xsd:integer  MONTH (xsd:dateTime arg)

以整数形式返回 arg 的月份部分。

此函数对应于 fn:month-from-dateTime

MONTH("2011-01-10T14:45:13.815-05:00"^^xsd:dateTime) 1
17.4.5.4 DAY
xsd:integer  DAY (xsd:dateTime arg)

以整数形式返回 arg 的日部分。

此函数对应于 fn:day-from-dateTime

day("2011-01-10T14:45:13.815-05:00"^^xsd:dateTime) 10
17.4.5.5 HOURS
xsd:integer  HOURS (xsd:dateTime arg)

以整数形式返回 arg 的小时部分。该值与 XSD dateTime 的词汇形式中给出的值一致。

此函数对应于 fn:hours-from-dateTime

HOURS("2011-01-10T14:45:13.815-05:00"^^xsd:dateTime) 14
17.4.5.6 MINUTES
xsd:integer  MINUTES (xsd:dateTime arg)

返回 arg 词汇形式中的分钟部分。该值与 XSD dateTime 的词汇形式中给出的值一致。

此函数对应于 fn:minutes-from-dateTime

MINUTES("2011-01-10T14:45:13.815-05:00"^^xsd:dateTime) 45
17.4.5.7 SECONDS
xsd:decimal  SECONDS (xsd:dateTime arg)

返回 arg 词汇形式中的秒部分。

此函数对应于 fn:seconds-from-dateTime

SECONDS("2011-01-10T14:45:13.815-05:00"^^xsd:dateTime) 13.815
17.4.5.8 TIMEZONE
xsd:dayTimeDuration  TIMEZONE (xsd:dateTime arg)

以 xsd:dayTimeDuration 形式返回 arg 的时区部分。 如果没有时区,则引发错误。

此函数对应于 fn:timezone-from-dateTime, 但对没有时区的字面量的处理除外。

TIMEZONE("2011-01-10T14:45:13.815-05:00"^^xsd:dateTime) "-PT5H"^^xsd:dayTimeDuration
TIMEZONE("2011-01-10T14:45:13.815Z"^^xsd:dateTime) "PT0S"^^xsd:dayTimeDuration
TIMEZONE("2011-01-10T14:45:13.815"^^xsd:dateTime) error
17.4.5.9 TZ
xsd:string  TZ (xsd:dateTime arg)

以数据类型为 xsd:string 的字面量形式返回 arg 的时区部分。 如果没有时区,则返回空字符串。

TZ("2011-01-10T14:45:13.815-05:00"^^xsd:dateTime) "-05:00"
TZ("2011-01-10T14:45:13.815Z"^^xsd:dateTime) "Z"
TZ("2011-01-10T14:45:13.815"^^xsd:dateTime) ""

17.4.6 三元组项上的函数

17.4.6.1 TRIPLE
triple term  TRIPLE (RDF term subj, RDF term pred, RDF term obj)
<<( subj pred obj )>>

如果三元组组(subjpredobj) 是一个 RDF 三元组 (也就是说,subjIRIblank nodepredIRI; 并且 objIRItriple termblank nodeliteral), 则该函数返回一个具有这三个元素的三元组项。 否则,该函数引发错误。

作为简写记法,TRIPLE 函数 也可以使用 <<()>>, 以三元组项表达式的形式书写。 这种简写形式有语法限制:

  • 三元组项表达式的三个元素中的每一个都只能是 变量 或直接写出的 RDF 项,而不能是任意表达式。
  • 主语和谓语位置的语法限于 IRI变量

函数形式 TRIPLE 可以与任意表达式一起使用。

VERSION "1.2"
PREFIX : <http://example/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?s ?date {
    ?s ?p ?o .
    BIND( <<( ?s ?p ?o )>> AS ?tt )
    :myreifier rdf:reifies ?tt .
    :myreifier :tripleAdded ?date .
}
VERSION "1.2"
PREFIX : <http://example/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?s ?date {
    ?s ?p ?o .
    BIND( TRIPLE(?s, ?p, ?o) AS ?tt )
    :myreifier rdf:reifies ?tt .
    :myreifier :tripleAdded ?date .
}
17.4.6.2 SUBJECT
RDF term  SUBJECT (triple term triple-term)

如果参数是一个 triple term, 该函数返回该三元组项的 subject。 如果参数不是 triple term, 则引发错误。

17.4.6.3 PREDICATE
RDF term  PREDICATE (triple term triple-term)

如果参数是一个 triple term, 该函数返回该三元组项的 predicate。 如果参数不是 triple term, 则引发错误。

17.4.6.4 OBJECT
RDF term  OBJECT (triple term triple-term)

如果参数是一个 triple term, 该函数返回该三元组项的 object。 如果参数不是 triple term, 则引发错误。

17.4.6.5 isTRIPLE
xsd:boolean  isTRIPLE (RDF term term)

如果参数是一个triple term, 该函数返回 true。 如果参数是任何其他种类的 RDF 项, 该函数返回 false。

17.4.7 哈希函数

17.4.7.1 MD5
xsd:string  MD5 (xsd:string arg)

返回根据 xsd:string 的词汇形式计算出的 MD5 校验和, 表示为十六进制数字字符串。十六进制数字应该为小写。

MD5("abc") "900150983cd24fb0d6963f7d28e17f72"
17.4.7.2 SHA1
xsd:string  SHA1 (xsd:string arg)

返回根据 xsd:string 的词汇形式计算出的 SHA1 校验和, 表示为十六进制数字字符串。十六进制数字应该为小写。

SHA1("abc") "a9993e364706816aba3e25717850c26c9cd0d89d"
17.4.7.3 SHA256
xsd:string  SHA256 (xsd:string arg)

返回根据 xsd:string 的词汇形式计算出的 SHA256 校验和, 表示为十六进制数字字符串。十六进制数字应该为小写。

SHA256("abc") "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
17.4.7.4 SHA384
xsd:string  SHA384 (xsd:string arg)

返回根据 xsd:string 的词汇形式计算出的 SHA384 校验和, 表示为十六进制数字字符串。十六进制数字应该为小写。

SHA384("abc") "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"
17.4.7.5 SHA512
xsd:string  SHA512 (xsd:string arg)

返回根据 xsd:string 的词汇形式计算出的 SHA512 校验和, 表示为十六进制数字字符串。十六进制数字应该为小写。

SHA512("abc") "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"

17.5 XPath 构造器函数

SPARQL 导入了 XPath 和 XQuery 函数与运算符 3.1 [XPATH-FUNCTIONS-31] 第 19.1 从 原始类型到原始类型的转换中定义的一部分 XPath 构造器函数。 SPARQL 构造器包括适用于 SPARQL 操作数数据类型的所有 XPath 构造器,以及 RDF 数据模型所施加的 附加数据类型。 SPARQL 中的转换通过在源类型操作数上调用目标类型的构造器函数来执行。

XPath 只定义了从一种 XML Schema 数据类型到另一种数据类型的转换。其余转换 定义如下:

下表概述始终允许(Y)、 从不允许(N)以及依赖于词汇 值(M)的转换操作。例如,从 xsd:string(第一行)到 xsd:float(第二列)的转换操作 依赖于词汇值(M)。

bool = xsd:boolean
dbl = xsd:double
flt = xsd:float
dec = xsd:decimal
int = xsd:integer
dT = xsd:dateTime
str = xsd:string
IRI = IRI

From \ To str flt dbl dec int dT bool
str Y M M M M M M
flt Y Y Y M M N Y
dbl Y Y Y M M N Y
dec Y Y Y Y Y N Y
int Y Y Y Y Y N Y
dT Y N N N N Y N
bool Y Y Y Y Y N Y
IRI Y N N N N N N

17.6 可扩展值测试

应注意,任何被指定为在某些条件下返回错误的函数或运算符, 都是有效的扩展点。也就是说,实现可以在这些错误情形中返回 非错误值,并且仍然符合本推荐标准。

PrimaryExpression 文法规则可以是对由 IRI 命名的扩展函数的调用。扩展函数接受若干 RDF 项作为参数,并返回一个 RDF 项。 这些函数的语义由标识该函数的 IRI 标识。

使用扩展函数的 SPARQL 查询可能具有有限的互操作性。

例如,考虑一个名为 func:even 的函数:

xsd:boolean   func:even (numeric value)

此函数可在 FILTER 中按如下方式调用:

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX func: <http://example.org/functions#>
SELECT ?name ?id
WHERE { 
    ?x foaf:name  ?name ;
       func:empId   ?id .
    FILTER (func:even(?id))
}

再举第二个例子,考虑一个计算两点之间距离的函数 aGeo:distance,此处用它查找 Grenoble 附近的地点:

xsd:double   aGeo:distance (numeric x1, numeric y1, numeric x2, numeric y2)
PREFIX aGeo: <http://example.org/geo#>

SELECT ?neighbor
WHERE {
    ?a aGeo:placeName "Grenoble" .
    ?a aGeo:locationX ?axLoc .
    ?a aGeo:locationY ?ayLoc .

    ?b aGeo:placeName ?neighbor .
    ?b aGeo:locationX ?bxLoc .
    ?b aGeo:locationY ?byLoc .

    FILTER ( aGeo:distance(?axLoc, ?ayLoc, ?bxLoc, ?byLoc) < 10 ) .
}

扩展函数可能用于测试核心 SPARQL 规范不支持的某种应用数据类型; 它也可能是在数据类型格式之间进行转换,例如从另一种日期格式 转换为 XSD dateTime RDF 项。

18. SPARQL 的定义

本节定义在给定查询字符串和 RDF 数据集的情况下,对图模式和解 修饰符求值的正确行为。它并不意味着 SPARQL 实现 必须使用这里定义的过程。

执行 SPARQL 查询的结果由一系列步骤定义,从作为字符串的 SPARQL 查询开始,将该字符串转为抽象语法形式,然后将 抽象语法转为由 SPARQL 代数中的运算符构成的 SPARQL 抽象查询。随后在 RDF 数据集上 对该抽象查询求值。

18.1 初始定义

18.1.1 RDF 数据集

RDF 数据集的概念定义于 [RDF12-CONCEPTS]。

对于以下定义,我们将每个 RDF 数据集捕获为一个集合:

{ G, (<u1>, G1), (<u2>, G2), ... (<un>, Gn) } 其中 G 和每个 Gi 都是图,并且每个 <ui> 是 IRI 或空白 节点。每个 <ui> 都彼此不同。

G 称为默认图。(<ui>, Gi) 称为命名 图。

定义:活动图

活动图是数据集中用于基本图模式 匹配的图。

18.1.2 查询变量

定义:查询变量

我们假定有一个可数无限集合 V,它与所有 RDF 项的集合不相交。 该集合 V 的每个成员都是一个 查询变量

18.1.3 三元组模式

定义:三元组模式

三元组模式是一个 3 元组, 它按如下方式归纳定义: 如果

则 (s, p, o) 是一个三元组模式。

三元组模式不允许循环 (即,一个三元组模式不能包含其自身)。

该三元组模式定义包含字面量主语。 RDF-core 已注意到这一点

“[RDF core 工作组]注意到,它不知道有什么理由不允许字面量作为 主语,并且未来具有较少限制性章程的 WG 可能 扩展语法以允许字面量作为语句的主语。”

由于 RDF 图不能包含字面量主语,任何以字面量作为主语的 SPARQL 三元组模式都无法在任何 RDF 图上匹配。

主语位置包含另一个三元组模式的三元组模式 将无法在任何 RDF 图上匹配, 因为 RDF 三元组不能在其主语位置具有 三元组项

18.1.4 基本图模式

定义:基本图模式

基本图模式三元组模式的集合。

空图模式是一个为空集合的基本图模式。

18.1.5 属性路径模式

定义:属性路径

属性路径是三元组序列 ST 中的三元组 ti 的序列,其中 n = length(ST)-1,使得对于 i=0 到 n,ti 的宾语与 ti+1 的主语为同一项。

我们称 t0 的主语为路径的起点。

我们称 tn 的宾语为路径的终点。

如果每个 ti 都是 G 的三元组,则属性路径是图 G 中的一条路径。

属性路径不会跨越一个数据集中的多个图。

定义:属性路径表达式

属性路径表达式是使用上文所述属性路径形式的表达式。

定义:属性路径模式

属性路径模式是一个 3 元组 (s, p, o),其中:

属性路径模式是三元组 模式的泛化,用于在谓语位置包含属性路径表达式。

18.1.6 解映射

解映射是从一组变量到一组 RDF 项的映射。在含义清楚时,我们使用 “解”这个术语。

定义:解映射

解映射 μ 是一个偏函数 μ : VT,其中 V 是所有变量的集合,并且 T 是所有 RDF 项的集合。

μ 的定义域,记为 dom(μ),是 V 中使 μ 有定义的子集。

定义:解序列

解序列是解的列表,可能是无序的。

写作 expr(μ) 表示表达式 expr 的值,该值使用 μ 给出的变量项。求值可能产生错误。

18.1.7 解序列 修饰符

定义:解序列修饰符

解序列修饰符是以下之一:

  • Order By 修饰符:将解排序
  • 投影修饰符:选择某些变量
  • Distinct 修饰符:确保序列中的解 是唯一的
  • Reduced 修饰符:允许消除任何非 distinct 解
  • Offset 修饰符:控制解在整个解序列中 从何处开始
  • Limit 修饰符:限制解的数量

18.1.8 SPARQL 查询

定义:SPARQL 查询

SPARQL 抽象查询是一个元组 (E, DS, QF), 其中:

定义:查询层级

查询层级是图模式、一组分组和聚合,以及一组 解修饰符。

查询是一棵“查询层级”的树,其中每个子查询 在该树中形成一个查询层级。

18.2 代数语法

为了定义 SPARQL 查询的求值语义, 首先将 SPARQL 查询字符串的抽象语法树 (由 SPARQL 文法定义) 转换为一种类似于 SPARQL 代数的语法。 本节定义可以在该代数语法中形成的表达式, 然后在第 18.3 转换到代数语法中定义 SPARQL 查询字符串到该代数语法的转换。

代数查询表达式 按如下方式递归定义:

如前一定义所使用的 代数属性路径表达式概念, 按如下方式递归定义:

18.3 转换到 代数语法

本节定义将 SPARQL 查询字符串中的图模式和解修饰符转换为 代数 查询表达式的过程。所描述的过程转换一个 查询嵌套层级,该层级由使用嵌套 SELECT 语法的子查询形成, 并递归应用于子查询。每个层级由图模式匹配和 过滤组成,随后应用解修饰符。

解析 SPARQL 查询字符串,并应用第 4. SPARQL 语法中给出的 IRI 和三元组模式缩写。 此时,抽象语法树由以下内容组成:

模式 修饰符 查询形式 其他
RDF 项 DISTINCT SELECT VALUES
属性路径表达式 REDUCED CONSTRUCT SERVICE
属性路径模式 投影 DESCRIBE  
ORDER BY ASK  
OPTIONAL LIMIT    
UNION OFFSET    
GRAPH Select 表达式    
BIND      
GROUP BY      
HAVING      
MINUS      
FILTER      

18.3.1 变量作用域

如果在查询的 代数表达式求值过程中的某一点, 存在某种方式使变量处于解映射的定义域中,则我们定义该变量为 在作用域内。下面的定义提供了一种从查询的 抽象语法树确定这一点的方法。

请注意,带有投影的子查询可以隐藏变量;在 FILTERMINUS 中使用变量不会使该变量在这些形式之外 处于作用域内。

PP1P2 为图模式,并令 EE1,..., 到 En 为表达式。变量 v 在作用域内,如果:

语法形式 作用域内变量
基本图模式(BGP) v 出现在 BGP 中
路径 v 出现在路径中
GroupGraphPattern { P1 P2 ... } 如果 v 在 P1、P2、... 中的一个或多个内处于作用域内,则 v 在作用域内
GRAPH X { P } X 是变量 v,或 v 在 P 中处于作用域内
{ P1 } UNION { P2 } v 在 P1 中处于作用域内或在 P2 中处于作用域内
OPTIONAL {P} v 在 P 中处于作用域内
SERVICE X {P} X 是变量 v,或 v 在 P 中处于作用域内
BIND (expr AS v) v 在作用域内
SELECT .. v .. { P } v 在作用域内
SELECT ... (expr AS v) v 在作用域内
GROUP BY ... v v 在作用域内
GROUP BY ... (expr AS v) v 在作用域内
SELECT * { P } vP 中处于作用域内
VALUES v { values } v 在作用域内
VALUES varlist { values } 如果 vvarlist 中,则 v 在作用域内

变量 v(expr AS v) 形式的位置上 不得处于作用域内。(expr AS v) 的作用域会立即应用于 SELECT 表达式。

BIND (expr AS v) 要求变量 v 不得从 使用它的组图模式中的前序元素处于作用域内。

SELECT 中,变量 v 不得在 SELECT 子句的图模式中处于作用域内,也不得在该子句中更早的另一个 select 表达式中使用。

18.3.2 转换图模式

本节描述将 SPARQL 图模式转换为 代数查询表达式的过程。该 过程应用于构成查询 WHERE 子句的组图模式 (大括号(“{ }”)定界符之间的单元), 并递归应用于组图模式中的每个语法元素。 转换结果是一个代数查询表达式

概括来说,步骤按如下方式应用:

我们写作

translate(graph pattern)

表示这里描述的用于转换图模式的算法。

工作组注意到,在 SPARQL 1.0 中,应用简化步骤的时机会导致涉及 optional 中双重嵌套过滤器和模式的查询发生含混转换:
OPTIONAL { { ... FILTER ( ... ?x ... ) } }..

这由两个非规范性测试用例说明:

在所有图模式转换之后应用简化步骤是 首选解读。

18.3.2.1 展开语法形式

展开第 4. SPARQL 语法中给出的 IRI 和三元组模式缩写。

18.3.2.2 收集 FILTER 元素

FILTER 表达式应用于其出现所在的整个组图模式。 执行过滤的代数运算符会在每个组元素转换之后添加到组中。 我们在此将过滤器收集到一起并将它们从组中移除,然后 将它们应用于整个已转换的组 图模式

Let FS := empty set
For each form FILTER(expr) in the group graph pattern
    FS := FS ∪ {expr}
    End

过滤表达式集合 FS 将在稍后使用

18.3.2.3 转换属性路径表达式

下表给出了 SPARQL 查询字符串中 属性路径表达式代数属性路径表达式的转换。 这会递归应用于属性路径表达式的所有元素。

此步骤之后的下一步会将 某些形式转换为三元组模式,随后这些三元组模式会通过相邻性 (没有中间的组模式定界符 {}) 或 其他语法形式)转换为基本图模式。总体而言,SPARQL 语法中仅由 IRI 组成的属性路径会成为三元组 模式,并被聚合到基本图模式中。

注:

  • 否定属性集合(NPS)中 IRI 和 ^IRI 形式的顺序无关。
语法形式(path) 代数形式(path)
iri Link(iri)
^path Inv(path)
!(:iri1|...|:irin) NPS({:iri1 ... :irin})
!(^:iri1|...|^:irin) Inv( NPS({:iri1 ... :irin}) )
!(:iri1|...|:irii|^:irii+1|...|^:irim)  Alt( NPS({:iri1 ...:irii}),
    Inv(NPS({:irii+1, ..., :irim})) )
path1 / path2 Seq(path1, path2)
path1 | path2 Alt(path1, path2)
path* ZeroOrMorePath(path)
path+ OneOrMorePath(path)
path? ZeroOrOnePath(path)
18.3.2.4 转换 属性路径模式

前一步转换了属性路径表达式。 此步骤转换属性路径模式, 后者由一个主语端点、一个属性路径表达式和一个宾语 端点组成。 此步骤假定属性路径模式的属性路径表达式 已经以 代数属性路径表达式形式给出。 此步骤的结果可能是三元组模式,以及 形式为 Path(...) 的 代数查询表达式

注:

  • xyRDF 项变量
  • var 是一个新的变量
  • ppeppe1ppe2代数属性路径表达式
  • 这些只应用于属性路径模式,而不应用于属性路径 表达式内部。
  • 表中较早的转换优先于最后的 转换应用。
  • 最终转换只是包装任何剩余的属性路径表达式,以使用 通用形式 Path(...)。
代数形式(path) 转换
x Link(iri) y x iri y
x Inv(iri) y y iri x
x Seq(ppe1, ppe2) y x ppe1 var . var ppe2 y
x ppe y Path(x, ppe, y)
Issue 226:属性路径模式转换不完整 spec:bug
我假定此表中的转换规则意在递归应用, 但本节没有对此作任何说明。特别是对于 “x Seq(ppe1, ppe2) y” 情形:所得转换中的 ppe1ppe2 仍可能是任意代数属性路径表达式,因此 转换应再次应用于两个所得的属性路径模式 (即 “x ppe1 var” 和 “var ppe2 y”)。

整个路径转换过程的示例(?_V 是一个新 变量):

?s :p/:q ?o
?s :p ?_V .
?_V :q ?o
?s :p* ?o
Path(?s, ZeroOrMorePath(Link(:p)), ?o)
:list rdf:rest*/rdf:first ?member
Path(:list, ZeroOrMorePath(Link(rdf:rest)), ?_V) .
?_V rdf:first ?member
18.3.2.5 转换 基本图模式

在转换属性路径之后,任何相邻的三元组模式都会被收集到一起 以形成基本图模式 BGP(triples)

18.3.2.6 转换图 模式

接下来,我们转换每个剩余的图模式形式,递归应用 转换过程。

如果形式是 GroupOrUnionGraphPattern

Let A := undefined
          
For each element G in the GroupOrUnionGraphPattern
    If A is undefined
        A := Translate(G)
    Else
        A := Union(A, Translate(G))
    End

The result is A

如果形式是 GraphGraphPattern

If the form is GRAPH IRI GroupGraphPattern
    The result is Graph(IRI, Translate(GroupGraphPattern))
If the form is GRAPH Var GroupGraphPattern
    The result is Graph(Var, Translate(GroupGraphPattern))

如果形式是 GroupGraphPattern

Let G := ContextSolution

For each element E in the sequence of elements in the GroupGraphPattern

    If E is of the form OPTIONAL{P} 
        Let A := Translate(P)
        If A is of the form Filter(F, A2)
            G := LeftJoin(G, A2, F)
        Else 
            G := LeftJoin(G, A, true)
            End
        End

    If E is of the form MINUS{P}
        G := Minus(G, Translate(P))
        End

    If E is of the form BIND(expr AS var)
        G := Extend(G, var, expr)
        End

    If E is any other form 
        Let A := Translate(E)
        G := Join(G, A)
        End

   End
   
The result is G.

如果形式是 InlineData

The result is a multiset data of solution mappings.
data 通过从变量列表(或单个变量)中对应位置的变量形成解映射而形成; 如果 DataBlockValue 是单词 UNDEF,则省略一个绑定。

如果形式是 SubSelect

The result is ToMultiset(Translate(SubSelect))
18.3.2.7 组的过滤器

在组完成转换之后,会添加过滤表达式,使其将应用于组中其余部分的整体:

If FS is not empty
    Let G := output of preceding step
    Let X := Conjunction of expressions in FS
    G := Filter(X, G)
End
18.3.2.8 简化步骤

某些只包含一个图模式的组会变成 Join(Z, A),其中 Z 是空基本 图 模式(即空集合)。这些会被替换为 A。空 图模式 Z 是 join 的单位元:

Replace Join(Z, A) by A
Replace Join(A, Z) by A

18.3.3 已映射图模式的示例

重写示例的第二种形式,是第一种形式经简化步骤移除空组 join 后的结果。 Z 是空基本图模式。

示例:包含由单个三元组模式组成的基本图模式的组:

{ ?s ?p ?o }
Join(Z, BGP(?s ?p ?o) )
BGP(?s ?p ?o)

示例:包含由两个三元组模式组成的基本图模式的组:

{ ?s :p1 ?v1 ; :p2 ?v2 }
BGP( ?s :p1 ?v1 . ?s :p2 ?v2 )
Issue 246:图模式转换示例 不一致 spec:editorial
上面的示例没有包含简化步骤之前所得表达式的版本。 下面其他几个示例也是如此。这些示例在这方面应该保持一致。

示例:由两个基本图模式的 union 组成的组:

{ { ?s :p1 ?v1 } UNION {?s :p2 ?v2 } }
Union(Join(Z, BGP(?s :p1 ?v1)),
      Join(Z, BGP(?s :p2 ?v2)) )
Union( BGP(?s :p1 ?v1) , BGP(?s :p2 ?v2) )

示例:由一个 union 和一个基本图模式的 union 组成的组:

{ { ?s :p1 ?v1 } UNION {?s :p2 ?v2 } UNION {?s :p3 ?v3 } }
Union(
    Union( Join(Z, BGP(?s :p1 ?v1)),
           Join(Z, BGP(?s :p2 ?v2))) ,
    Join(Z, BGP(?s :p3 ?v3)) )
Union(
    Union( BGP(?s :p1 ?v1) ,
           BGP(?s :p2 ?v2),
    BGP(?s :p3 ?v3))

示例:由一个基本图模式和一个 optional 图模式组成的组:

{ ?s :p1 ?v1 OPTIONAL {?s :p2 ?v2 } }
LeftJoin(
    Join(Z, BGP(?s :p1 ?v1)),
    Join(Z, BGP(?s :p2 ?v2)),
    true)
LeftJoin(BGP(?s :p1 ?v1), BGP(?s :p2 ?v2), true)

示例:由一个基本图模式和两个 optional 图模式组成的组:

{ ?s :p1 ?v1 OPTIONAL {?s :p2 ?v2 } OPTIONAL { ?s :p3 ?v3 } }
LeftJoin(
    LeftJoin(
        BGP(?s :p1 ?v1),
        BGP(?s :p2 ?v2),
        true) ,
    BGP(?s :p3 ?v3),
    true)

示例:由一个基本图模式和一个带有 filter 的 optional 图模式组成的组:

{ ?s :p1 ?v1 OPTIONAL {?s :p2 ?v2 FILTER(?v1<3) } }
LeftJoin(
     Join(Z, BGP(?s :p1 ?v1)),
     Join(Z, BGP(?s :p2 ?v2)),
     (?v1<3) )
LeftJoin(
    BGP(?s :p1 ?v1) ,
    BGP(?s :p2 ?v2) ,
   (?v1<3) )

示例:由一个 union 图模式和一个 optional 图模式组成的组:

{ {?s :p1 ?v1} UNION {?s :p2 ?v2} OPTIONAL {?s :p3 ?v3} }
LeftJoin(
  Union(BGP(?s :p1 ?v1),
        BGP(?s :p2 ?v2)) ,
  BGP(?s :p3 ?v3) ,
  true )

示例:由一个基本图模式、一个 filter 和一个 optional 图 模式组成的组:

{ ?s :p1 ?v1 FILTER (?v1 < 3 ) OPTIONAL {?s :p2 ?v2} }
Filter( ?v1 < 3 ,
  LeftJoin( BGP(?s :p1 ?v1), BGP(?s :p2 ?v2), true) ,
  )

示例:涉及 BIND 的模式:

{ ?s :p ?v . BIND (2*?v AS ?v2) ?s :p1 ?v2 }
Join(
   Extend( BGP(?s :p ?v), ?v2, 2*?v) ,
   BGP(?s :p1 ?v2) )

示例:涉及 BIND,且带有 简化步骤的模式:

Issue 246:图模式转换示例 不一致 spec:editorial
以下示例在所得表达式的第一个版本(即简化步骤之前的版本)中使用 {} 表示空 BGP,而上面的前几个示例则改用 Z。这些示例在这方面应该保持一致。
{ ?s :p ?v . {} BIND (2*?v AS ?v2) }
Extend(
   Join(
     Join( {}, BGP(?s :p ?v)),
     {}),
   ?v2, 2*?v
)
Extend(
   BGP(?s :p ?v) ,
   ?v2, 2*?v
)

示例:涉及 MINUS 的模式:

{ ?s :p ?v . MINUS {?s :p1 ?v2 } }
Minus(
   BGP(?s :p ?v) ,
   BGP(?s :p1 ?v2)
)

示例:涉及子查询的模式:

{ ?s :p ?o . {SELECT DISTINCT ?o {?o ?p ?z} } }
Join(
   BGP(?s :p ?o) ,
   ToMultiset(
     Distinct(
       Project( ToList(BGP(?o ?p ?z)), {?o} )
     )
   )
)

18.3.4 转换组、聚合、HAVING、最终 VALUES 子句和 SELECT 表达式

在此步骤中,我们按以下顺序处理查询层级上的子句:

  • 分组
  • 聚合
  • HAVING
  • VALUES
  • Select 表达式
18.3.4.1 分组和 聚合

步骤:GROUP BY

如果使用了 GROUP BY 关键字,或者由于在 HAVINGORDER BY 子句中,或在 投影中使用聚合而存在隐式分组,则通过 Group 函数执行分组。 在这种情况下,在分组之前,通过应用 ToList 函数 将解集转换为解序列。 接下来,Group 函数 将此解序列划分为由一个或 多个解组成的组,并具有相同的总体基数。对于隐式分组,使用一个固定 常量 (1) 将所有解分到单个组中。

步骤:聚合

聚合步骤作为查询层级上的转换应用,将 查询层级中的聚合表达式替换为 Aggregation() 代数 表达式。

使用任何聚合的查询层级的转换如下给出:

Issue 247:分组和聚合的转换算法中有 一些小问题 spec:editorial
以下算法中有几个小问题。
Let A := the empty sequence
Let Q := the query level being evaluated
Let P := algebraic query expression produced for the GroupGraphPattern of the query level
Let E := [], a list of pairs of the form (variable, expression)

If Q contains GROUP BY exprlist
   Let Grp := Group(exprlist, ToList(P))
Else If Q contains an aggregate in SELECT, HAVING, ORDER BY
   Let Grp := Group((1), ToList(P))
Else
   skip the rest of the Aggregates step
   End

Global i := 1   # Initially 1 for each query processed

For each (X AS Var) in SELECT, each HAVING(X), and each ORDER BY X in Q
  For each unaggregated variable V in X
      Replace V with SAMPLE(V)
      End
  For each aggregate R(args ; scalarvals) now in X
      # note: scalarvals may be omitted; if so, it is equivalent to the empty function
      Ai := Aggregation(args, R, scalarvals, Grp)
      Replace R(...) with aggi in Q
      i := i + 1
      End
  End

For each variable V appearing outside of an aggregate
   Ai := Aggregation(V, Sample, {}, Grp)
   E := E append (V, aggi)
   i := i + 1
   End

A := Ai, ..., Ai-1
P := AggregateJoin(A)

列表 E 将在第 18.3.4.4 SELECT 表达式中转换 SELECT 表达式时使用。

18.3.4.2 HAVING

HAVING 表达式使用与 FILTER() 相同的规则求值。 请注意,由于 HAVING 子句求值所在的逻辑位置, SELECT 子句所投影的表达式对 HAVING 子句不可见。

Let Q := the query level being evaluated
Let P := the algebraic query expression produced for the query level so far

For each HAVING(E) in Q
    P := Filter(E, P)
    End
18.3.4.3 VALUES

如果查询带有尾随 VALUES 子句:

Let P := the algebraic query expression produced for the query level so far
P := Join(P, ToMultiset(data))
  where data is a solution sequence derived from the VALUES clause

数据的转换与内联 数据相同。

18.3.4.4 SELECT 表达式

步骤:Select 表达式

我们需要考虑抽象语法的两种形式:

SELECT selItem ... { pattern }
SELECT * { pattern }
Let X := algebraic query expression from earlier steps
Let VS := set of all variables visible in the pattern,
           so restricted by sub-SELECT projected variables and GROUP BY variables.
           Not visible: only in filter, exists/not exists, masked by a subselect, 
                        non-projected GROUP variables, only in the right hand side of MINUS

Let PV := {}, a set of variable names
Let E := a list of pairs of the form (variable, expression), populated in Section 18.3.4.1 Grouping and Aggregation
  
If "SELECT *"
    PV := VS

If  "SELECT selItem ..."
    For each selItem
        If selItem is a variable
            PV := PV ∪ { variable }
        End
        If selItem is (expr AS var)
            var must not appear in VS nor in PV; if it does then generate a syntax error and stop
            PV := PV ∪ { var }
            E := E append (var, expr) 
        End
    End

For each pair (var, expr) in E
    X := Extend(X, var, expr)
    End
  
Result is X  
The set PV is used later for projection (see Section 18.3.5.2 Projection).

当变量被用作 AS 的命名目标(例如 ... AS ?x),且该变量在 SELECT 的 WHERE 子句内部使用,或已在此 SELECT 表达式中更早被用作 AS 的目标时,会产生语法错误。

18.3.5 转换解 修饰符

解修饰符应用于模式匹配之后的 SPARQL 查询处理。

由于解修饰符作用于 解映射序列,因此到此为止产生的查询结果首先会从 解映射的多重集转换为这样的序列。虽然此序列没有隐含的排序, 且重复项不必相邻,但该序列 就其包含的元素及其重数而言与多重集相同。 为应用这种从多重集到序列的转换, 将解修饰符转换为 代数查询表达式 的算法从以下步骤开始,其中 A 是 前一节算法产生的 代数查询表达式

Let M := ToList(A)

现在,按以下顺序应用解修饰符:

  • Order by
  • 投影
  • Distinct
  • Reduced
  • Offset
  • Limit
18.3.5.1 ORDER BY

如果查询字符串有 ORDER BY 子句

M := OrderBy(M, 排序比较器列表)

18.3.5.2 投影

投影变量集合 PV 已在 处理 SELECT 表达式时计算。

M := Project(M, PV)

18.3.5.3 DISTINCT

如果查询包含 DISTINCT,

M := Distinct(M)

18.3.5.4 REDUCED

如果查询包含 REDUCED,

M := Reduced(M)

18.3.5.5 OFFSET 和 LIMIT

如果查询包含 “OFFSET offset” 和 “LIMIT limit

M := Slice(M, offset, limit)

如果查询包含 “OFFSET offset”,但查询不包含 “LIMIT limit

M := Slice(M, offset)

如果查询包含 “LIMIT limit”,但查询不包含 “OFFSET offset

M := Slice(M, 0, limit)

18.3.5.6 最终 代数查询表达式
整体代数查询表达式为 M

18.4 基本图模式

在匹配图模式时,可能的解形成一个 多重集, 也称为 。多重集是一种 无序元素集合,其中每个元素可以出现多次。它由一个元素集合和一个给出这些 元素各自重数的函数来描述(即,该元素在多重集中包含的次数)。

写作 μ 表示解映射。

写作 μ0 表示这样的映射:dom(μ0) 是 空集合。

写作 Ω0 表示只包含空映射 μ0、且重数为 1 的多重集。这是 join 单位元。

写作 μ(x) 表示把变量 x 映射到 RDF 项 t 的解映射:{ (x, t) }。

定义:兼容映射

如果对于同时位于 dom(μ1) 和 dom(μ2) 中的每个 变量 v,都有 μ1(v) = μ2(v),则两个解映射 μ1 和 μ2 兼容。

这里,μ1(v) = μ2(v) 表示 μ1(v) 和 μ2(v) 是同一 RDF 项。

如果 μ1 和 μ2 兼容,则 μ1 ∪ μ2 也是 一个映射。写作 merge(μ1, μ2) 表示 μ1 ∪ μ2

定义:重数

给定一个由解映射组成的多重集 Ω 和一个解 映射 μ,我们写作 multiplicity(μ | Ω) 来表示 μΩ 中出现的次数。

类似地,给定一个解序列 Ψ 和一个解 映射 μ,我们写作 multiplicity(μ | Ψ) 来表示 μΨ 中出现的次数。

18.4.1 SPARQL 基本 图模式匹配

基本图模式会与查询该部分的活动图进行匹配。 可以通过把变量和空白节点都替换为项,来实例化基本图模式, 从而得到两种实例概念。空白节点使用从空白 节点到 RDF 项的 RDF 实例映射 σ 进行替换; 变量则由从查询变量到 RDF 项的解映射替换。

定义:模式实例映射

模式实例映射 P 是 RDF 实例映射 σ 和解映射 μ 的组合。P(x) = μ(σ(x))

对于 BGP “x”,P(x) 表示替换 x 中 σ 有定义的空白节点 b 为 σ(b),并替换 x 中 μ 有定义的所有变量 v 为 μ(v) 后所得的结果。

任何模式实例映射都会定义一个唯一的解映射和一个唯一的 RDF 实例 映射,分别通过将其限制到查询变量和空白节点而获得。

定义:基本图模式匹配

令 BGP 为一个基本图模式,令 G 为一个 RDF 图。

当存在一个模式实例映射 P,使得 P(BGP) 是 G 的子图,且 μ 是 P 限制到 BGP 中查询变量后的结果时,μ 是 BGP 从 G 得到的一个

multiplicity( μ | Ω ) = 不同 RDF 实例映射 σ 的数量,使得 P = μ(σ) 是一个模式实例映射,并且 P(BGP) 是 G 的子图。

如果一个基本图模式是空集合,则解为 Ω0

18.4.2 空白节点的处理

此定义允许解映射把基本图模式 BGP 中的变量绑定到 G 中的空白节点。由于 SPARQL 把结果格式 文档(SPARQL 查询结果 XML 格式(第二 版)SPARQL 1.1 查询结果 JSON 格式SPARQL 1.1 查询结果 CSV 和 TSV 格式)中的空白节点标识符视为以文档为作用域, 因而不能把它们理解为标识数据集活动图中的节点。如果 DS 是一个查询的数据集, 那么模式解因此被理解为不是来自 DS 本身的活动图, 而是来自一个称为作用域图的 RDF 图。这个图就是 DS 的活动图,但其中的空白节点会被统一替换为新的空白节点, 这些新空白节点既不在 DS 中,也不在 BGP 中,这与 合并 RDF 图时的做法相似。 同一个作用域图会用于单个查询的所有解。作用域图纯粹是一种理论 构造;在实践中,其效果只是通过空白节点标识符的文档作用域约定来获得。

由于 RDF 空白节点会让许多模式产生无限多的冗余解, 因此可能存在无限多个模式解(通过把空白节点替换为不同的 空白节点而获得)。因此,有必要以某种方式界定基本 图模式的解。SPARQL 使用子图匹配准则来确定基本 图模式的解。对于从基本图模式到活动图子集的每个不同模式实例映射, 都有一个解。

这针对计算的便利性而非冗余消除进行了优化。即使数据集的活动图是 精简的, 它也允许查询结果包含冗余,并允许逻辑等价的数据集 产生不同的查询结果。

18.5 属性路径模式

本节定义属性路径 模式的求值。属性路径模式由一个主语端点(一个 RDF 项或一个变量)、 一个属性路径表达式和一个对象端点组成。

属性路径表达式的转换 会把每个属性路径表达式 转换为一个代数属性路径表达式。 例如,属性路径表达式 (:p/:q)* 是一个涉及序列属性路径的 ZeroOrMorePath 表达式, 并被转换为代数属性路径表达式 ZeroOrMorePath( Seq(Link(:p), Link(:q)) )。

随后,属性路径模式的转换 会把其中一些代数属性路径表达式 转换为其他 SPARQL 图模式,例如把长度为一的属性路径转换为三元组 模式,而这些三元组模式又会被组合为基本图模式。 剩下的则是带有以下运算符的代数属性路径表达式: AltZeroOrOnePathZeroOrMorePathOneOrMorePathNPS, 以及这些运算符中包含的代数属性路径 表达式。

带有这些剩余代数属性路径表达式的属性路径模式 会以端点 XY代数语法形式 Path(X, ppe, X) 出现。

记法

为了表示属性路径模式的求值,对于每个形式为 Path(X, ppe, Y) 的 代数查询表达式, 我们写作如下:

ppeval(X, ppe, Y)

这会产生一个解 映射多重集,每个解映射都对所使用的变量有绑定(XY 中的每一个都可以 是变量)。某些运算符只产生解映射集合。

写作 x
x:term 一个 RDF 项
x:var 一个变量
Issue 349:属性路径模式求值中未显式给出被查询的图
ppeval 的签名应该扩展为: ppeval(X, ppe, Y, G), 其中 G 是一个 RDF 图。

所有求值都通过匹配整个查询求值中该点的活动图 来执行。为清晰起见,我们省略在每个定义中显式包含活动图。

定义:谓词属性路径的求值

iri 为一个 IRI。

ppeval(X, Link(iri), Y) = evaluation of basic graph pattern {X iri Y}

如果 XY 都是变量,这与如下形式相同:

ppeval(X:var, Link(iri), Y:var) =
    { (X, xn:term) (Y, yn:term) | triple (xn, iri, yn) is in the active graph }

如果 X 是变量,而 Y 是 RDF 项:

ppeval(X:var, Link(iri), Y:term) =
    { (X, xn:term) | triple (xn, iri, Y) is in the active graph }

如果 X 是 RDF 项,而 Y 是变量:

ppeval(X:term, Link(iri), Y:var) =
    { (Y, yn:term) | triple (X, iri, yn) is in the active graph }

如果 XY 都是 RDF 项:

ppeval(X:term, Link(iri), Y:term)
    = { μ0 } if triple (X, iri, Y) is in the active graph
    = { { } } = Ω0 

ppeval(X:term, Link(iri), Y:term) =
     { } if triple (X, iri, Y) is not in the active graph

非正式地说,求值谓词属性路径与在查询求值的该点执行一个 SELECT * { X iri Y } 子查询相同。

定义:逆属性路径的求值

ppe 为一个代数属性路径 表达式,则:

ppeval(X, Inv(ppe), Y) = ppeval(Y, ppe, X)

定义:序列属性路径的求值

ppe1ppe2代数属性路径表达式。令 V 为一个新变量。

ppeval(X, Seq(ppe1, ppe2), Y) = ToMultiSet( Project(ToList(A), PV) )

其中 A = Join( ppeval(X, ppe1, V), ppeval(V, ppe2, Y) ) 且 PV = { projVar ∈ {X,Y} | projVar 是 变量 }。

非正式地说,这与如下形式相同:

SELECT * { X P1 _:a . _:a P2 Y }

其中 P1 是一个 属性路径表达式, 它可以被转换为 代数属性路径表达式 ppe1, 而 P2 可以被转换为 ppe2。 这一观察基于这样的事实:空白节点 _:a 的行为类似于一个变量(在简单 蕴涵下),只是它不会出现在 SELECT * 的结果中。

定义:替代属性路径的求值

ppe1ppe2代数属性路径表达式

ppeval(X, Alt(ppe1, ppe2), Y) =
    Union( ppeval(X, ppe1, Y), ppeval(X, ppe2, Y) )

非正式地说,这与如下形式相同:

SELECT * { { X P1 Y } UNION { X P2 Y } }

其中 P1 是一个 属性路径表达式, 它可以被转换为 代数属性路径表达式 ppe1, 而 P2 可以被转换为 ppe2

定义:图的节点集合

G 的节点集合 nodes(G) 为:

nodes(G) = { n | n 是一个 RDF 项, 并作为 G 的某个断言三元组的主语或对象使用}

定义:ZeroOrOnePath 的求值

ppe 为一个代数属性路径 表达式。 令 G活动图

ppeval(X:term, ZeroOrOnePath(ppe), Y:var) = 
    { (Y, yn) | yn = X or {(Y, yn)} in ppeval(X, ppe, Y) }
ppeval(X:var, ZeroOrOnePath(ppe), Y:term) =
    { (X, xn) | xn = Y or {(X, xn)} in ppeval(X, ppe, Y) }
ppeval(X:term, ZeroOrOnePath(ppe), Y:term) = 
    { {} } if X = Y or ppeval(X,ppe,X) is not empty
    { } otherwise
ppeval(X:var, ZeroOrOnePath(ppe), Y:var) = 
    { (X, xn) (Y, yn) | 
        either (yn in nodes(G) and xn = yn)
        or {(X, xn), (Y, yn)} in ppeval(X, ppe, Y) }

我们定义一个辅助函数 ALP,用于 ZeroOrMorePathOneOrMorePath 的定义。请注意,这里给出的算法用于 指定该特性。实现者可以自由采用任何方法来实现求值,只要该方法对整个查询产生相同结果。 ZeroOrMorePathOneOrMorePath 形式会基于 由路径连接的不同节点返回匹配。

匹配算法基于跟随所有路径,并检测图节点(主语或对象) 何时已经在路径上被访问。

非正式地说,该算法尝试在每一步通过给定 代数属性路径表达式 ppe 的一次应用来扩展结果多重集,并记录此特定路径已经访问过哪些节点。 如果某个节点已在所考虑的路径上被访问,则它不会成为下一步的候选。

定义:函数 ALP

Let ppe be an algebraic property path expression.
Let reachableTerms(x:term, ppe) be the set of RDF terms
 reached by repeated matches of ppe,
 when starting at RDF term x.

  ALP(x:term, ppe) =
      Let V = empty set of terms
      ALP_recurse(x:term, ppe, V)
      return is V

  ALP_recurse(x:term, ppe, V:set of RDF terms) =
      if ( x in V ) return 
      add x to V
      X = reachableTerms(x, ppe)
      For n:term in X
          ALP_recurse(n, ppe, V)
          End

定义:ZeroOrMorePath 的求值

ppe 为一个代数属性路径 表达式。 令 G活动图

ppeval(X:term, ZeroOrMorePath(ppe), vy:var) =
    { { (vy, n) } | n in ALP(X, ppe) }

ppeval(vx:var, ZeroOrMorePath(ppe), vy:var) =
    { { (vx, t), (vy, n) } |  
      t in nodes(G), (vy, n) in ppeval(t, ZeroOrMorePath(ppe), vy) }

ppeval(vx:var, ZeroOrMorePath(ppe), y:term) = 
    ppeval(y:term, ZeroOrMorePath(Inv(ppe)), vx:var)

ppeval(x:term, ZeroOrMorePath(ppe), y:term) = 
    { { } } if { (vy:var,y) } in ppeval(x, ZeroOrMorePath(ppe), vy)
    { } otherwise

定义:OneOrMorePath 的求值

ppe 为一个代数属性路径 表达式。 令 G活动图

# For OneOrMorePath, we take one step of the path then start
# recording nodes for results.

ppeval(x:term, OneOrMorePath(ppe), vy:var) = { { (vy, t) } | t in V }
    where V is the set of RDF terms that is returned by the
    following algorithm.

    Let X = reachableTerms(x, ppe)
    Let V = the empty multiset
    For n in X
        ALP_recurse(n, ppe, V)
    End
    result is V

ppeval(vx:var, OneOrMorePath(ppe), vy:var) =
     { { (vx, t), (vy, n) } |
         t in nodes(G), (vy, n) in ppeval(t, OneOrMorePath(ppe), vy) }

ppeval(vx:var, OneOrMorePath(ppe), y:term) =
    ppeval(y:term, OneOrMorePath(Inv(ppe)), vx)

ppeval(x:term, OneOrMorePath(ppe), y:term) =
    { { } } if { (vy:var, y) } in ppeval(x, OneOrMorePath(ppe), vy)
    { } otherwise

定义:否定属性集合的求值

Write μ' as the extension of a solution mapping:
μ'(μ, x) = μ(x)   if x is a variable
μ'(μ, t) = t      if t is an RDF term
Let x and y be variables or RDF terms, S a set of IRIs,
and G the active graph.

   ppeval(x, NPS(S), y) =
       { μ | ∃ triple(μ'(μ, x), p, μ'(μ, y)) in G, such that the IRI of pS }

18.6 SPARQL 代数

对于 SPARQL 抽象查询中剩余的每个符号,我们定义一个用于 求值的运算符。同名的 SPARQL 代数运算符用于按照“求值 语义”一节中所述,对 SPARQL 抽象查询节点进行求值。基本图模式和属性路径模式的求值已经在上文描述。

定义:Filter

Ω 为一个解映射多重集, expr 为一个表达式D 为一个数据集G活动图。 我们定义:

Filter(expr, Ω, D, G) = { μ in Ω | expr(μ, D, G) is an RDF term t such that EBV(t) is "true"^^xsd:boolean }

multiplicity( μ | Filter(expr, Ω, D, G) ) = multiplicity( μ | Ω )

其中,对于每个解映射 μexpr(μ, D, G) 是 在具有活动图 G 的数据集 D 上下文中, 相对于 μ 求值表达式 expr 的结果。

定义:Join

Ω1Ω2 为解映射多重集。我们 定义:

Join(Ω1, Ω2) = { merge(μ1, μ2) | μ1 in Ω1 and μ2 in Ω2, and μ1 and μ2 are compatible }

multiplicity( μ | Join(Ω1, Ω2) ) =
    for each merge(μ1, μ2), μ1 in Ω1 and μ2 in Ω2 such that μ = merge(μ1, μ2),
        sum over (μ1, μ2), multiplicity( μ1 | Ω1 ) * multiplicity( μ2 | Ω2 )

Join 中的某个解映射 μ 可能由被连接的多重集中不同的解 映射 μ1μ2 产生。 μ 的重数是所有可能情况所得重数之和。

定义:Diff

Ω1Ω2 为解映射多重集, expr 为一个表达式D 为一个数据集G活动图。 我们定义:

Diff(Ω1, Ω2, expr, D, G) = { μ in Ω1 | for every μ' in Ω2, any of the following conditions holds:

  • μμ'兼容
  • μμ' 兼容expr(merge(μ, μ'), D, G) 是一个错误,或
  • μμ' 兼容expr(merge(μ, μ'), D, G) 是一个 RDF 项 t, 对它而言 EBV(t) 不是 "true"^^xsd:boolean

}

multiplicity( μ | Diff(Ω1, Ω2, expr, D, G) ) = multiplicity( μ | Ω1 )

其中,对于每个解映射 μexpr(μ, D, G) 是 在具有活动图 G 的数据集 D 上下文中, 相对于 μ 求值表达式 expr 的结果。

Diff 在内部用于定义 LeftJoin

定义:LeftJoin

Ω1Ω2 为解映射多重集, expr 为一个表达式D 为一个数据集G活动图。 我们定义:

LeftJoin(Ω1, Ω2, expr, D, G) = Filter(expr, Join(Ω1, Ω2), D, G) ∪ Diff(Ω1, Ω2, expr, D, G)

multiplicity( μ | LeftJoin(Ω1, Ω2, expr, D, G) ) = multiplicity( μ | Filter(expr, Join(Ω1, Ω2), D, G) ) + multiplicity( μ | Diff(Ω1, Ω2, expr, D, G) )

定义:Union

Ω1Ω2 为解映射多重集。我们 定义:

Union(Ω1, Ω2) = { μ | μ in Ω1 or μ in Ω2 }

multiplicity( μ | Union(Ω1, Ω2) ) = multiplicity( μ | Ω1 ) + multiplicity( μ | Ω2 )

定义:Minus

Ω1Ω2 为解映射多重集。我们 定义:

Minus(Ω1, Ω2) = { μ | μ in Ω1 . ∀ μ' in Ω2, either μ and μ' are not compatible or dom(μ) and dom(μ') are disjoint }

multiplicity( μ | Minus(Ω1, Ω2) ) = multiplicity( μ | Ω1 )

之所以添加对 dom(μ) 和 dom(μ') 的附加限制,是因为否则如果 Ω2 中存在一个解映射,它与 Ω1 中的解 映射没有任何共同变量,那么 Minus(Ω1, Ω2) 将为空, 而不管 Ω2 的其余部分如何。空解映射与 每个其他解映射都兼容,因此如果没有该限制,则对于任何 模式 PP MINUS {} 都会为空。

定义:Extend

μ 为一个解映射,Ω 为解映射多重集, var 为一个变量, expr 为一个表达式D 为一个数据集G活动图。 我们定义:

Extend(Ω, var, expr, D, G) = { Extend(μ', var, expr, D, G) | μ' in Ω },

multiplicity( μ | Extend(Ω, var, expr, D, G) ) = multiplicity( μ' | Ω ) if there exists a solution mapping μ' in Ω such that μ = Extend(μ', var, expr, D, G),

multiplicity( μ | Extend(Ω, var, expr, D, G) ) = 0 if no such solution mapping μ' exists in Ω,

其中,对于每个解映射 μ'

Extend(μ', var, expr, D, G) = μ' ∪ { (var, expr(μ', D, G)) } if var not in dom(μ') and expr(μ', D, G) is an RDF term,

Extend(μ', var, expr, D, G) = μ' if var not in dom(μ') and expr(μ', D, G) is an error,

Extend(μ', var, expr, D, G) is undefined if var in dom(μ'), and

expr(μ', D, G) 是 在具有活动图 G 的数据集 D 上下文中, 相对于 μ' 求值表达式 expr 的结果。

写作 [ x | C ] 表示由满足条件 C 的元素 x 组成的序列。

定义:ToList

Ω 为解映射多重集。我们定义:

ToList(Ω) = a sequence of mappings μ in Ω in any order, with multiplicity( μ | Ω ) occurrences of μ

multiplicity( μ | ToList(Ω) ) = multiplicity( μ | Ω )

定义:OrderBy

Ψ 为解映射序列。我们定义:

OrderBy(Ψ, condition) = [ μ | μ in Ψ and the sequence satisfies the ordering condition]

multiplicity( μ | OrderBy(Ψ, condition) ) = multiplicity( μ | Ψ )

定义:Project

Ψ 为解映射序列,PV 为一组变量。

对于映射 μ,写作 Proj(μ, PV),表示将 μ 限制到 PV 中变量后所得的映射。

Project(Ψ, PV) = [ Proj(μ, PV) | μ in Ψ ]

multiplicity( μ | Project(Ψ, PV) ) = sum( multiplicity( μ' | Ψ ) | μ' in Ψ such that μ' = Proj(μ, PV) )

Project(Ψ, PV) 的顺序必须 保留 OrderBy 给出的任何排序。

定义:Distinct

Ψ 为解映射序列。我们定义:

Distinct(Ψ) = [ μ | μ in Ψ ]

multiplicity( μ | Distinct(Ψ) ) = 1 for every μDistinct(Ψ)

multiplicity( μ | Distinct(Ψ) ) = 0 for every μDistinct(Ψ)

Distinct(Ψ) 的顺序必须保留 OrderBy 给出的任何排序。

定义:Reduced

Ψ 为解映射序列。我们定义:

Reduced(Ψ) = [ μ | μ in Ψ ]

multiplicity( μ | Reduced(Ψ) ) is between 1 and multiplicity( μ | Ψ ) for every μReduced(Ψ)

multiplicity( μ | Reduced(Ψ) ) = 0 for every μReduced(Ψ)

Reduced(Ψ) 的顺序必须保留 OrderBy 给出的任何排序。

Reduced 解序列修饰符不保证 已定义的重数。

定义:Slice

Ψ 为解映射序列,并令 offsetlimit 为 非负整数。我们定义:

Slice(Ψ, offset) = Ψ0   if offsetCard(Ψ)

Slice(Ψ, offset) = subseq(Ψ, offset+1, Card(Ψ))   if 0 ≤ offset < Card(Ψ)

Slice(Ψ, offset, limit) = Ψ0   if offsetCard(Ψ) or limit = 0

Slice(Ψ, offset, limit) = subseq(Ψ, offset+1, Card(Ψ))   if 0 ≤ offset < Card(Ψ) and limitCard(Ψ)−offset

Slice(Ψ, offset, limit) = subseq(Ψ, offset+1, offset+limit)   if 0 ≤ offset < Card(Ψ) and 0 < limit < Card(Ψ)−offset

其中 Ψ0 是空解映射序列, 并且对于每两个整数 ij, subseq(Ψ, i, j) 是 Ψ 的子序列, 它从 Ψ 的第 i 个元素开始, 到 Ψ 的第 j 个元素结束。

注意,此定义假定序列以 1 为基, 且子序列在两端都是包含的 (即,以第 j 个元素结束意味着 该子序列包含 Ψ 的第 j 个元素作为最后一个元素)。

定义:ToMultiSet

Ψ 为一个解序列。我们定义:

ToMultiSet(Ψ) = { μ | μ in Ψ }

multiplicity( μ | ToMultiSet(Ψ) ) = multiplicity( μ | Ψ )

18.6.1 聚合代数

Group 是一个函数,它根据 解的某些属性,把解序列分组为 多个解。

定义:Group

Group 会针对一个 解序列 Ψ 求值表达式列表,从而产生一个 从键到解序列的偏函数。

Group(exprlist, Ψ) = { ListEval(exprlist, μ) → [ μ' | μ' in Ψ such that ListEval(exprlist, μ') and ListEval(exprlist, μ) are the same ] | μ in Ψ },

其中,如果两个列表 LL'(由 ListEval 函数产生)具有 相同数量的元素,并且对于这两个列表中的每个 位置 k,以下两个条件之一为真,则认为它们 相同:

  • L 的第 k 个位置的元素 是一个 RDF 项;L' 的第 k 个 位置的元素也是一个 RDF 项;并且这两个 RDF 项是同一项
  • L 的第 k 个位置的元素 是一个错误,且 L' 的第 k 个位置的 元素也是一个错误

定义:ListEval

ListEval((expr1, ..., exprn), μ) returns a list (e1, ..., en), where ei = expri(μ) or error.

ListEval 保留列表 元素求值所产生的错误。

请注意,虽然 ListEval 的结果 可能包含错误,并且错误可用于 分组,但包含错误值的解会在对组和任何聚合函数求值 结束时被移除。

还要注意,ListEval((unbound), μ) 的结果是列表 (error),因为对未绑定表达式求值会产生 错误。

Aggregation 是一个函数,它计算聚合 表达式输出的标量值。它用于 SELECT 子句、HAVING 求值过程,以及 ORDER BY(在需要时)中。Aggregation 会 使用集合函数,在解的分组上计算聚合值。

定义:Aggregation

exprlist 为表达式列表或 *func 为集合 函数; scalarvals 为从查询中的聚合传递来的偏函数(可能定义域为空); 并令 { key1Ψ1, ..., keymΨm } 为分组步骤产生的、 从键到 解序列的偏函数。

Aggregation 把集合函数 func 应用于给定集合,并为每个键及该键对应的一组解产生 单个值。

Aggregation(exprlist, func, scalarvals, { key1Ψ1, ..., keymΨm } )
   = { (key, F(Ψ)) | keyΨ in { key1Ψ1, ..., keymΨm } }

where
  M(Ψ) = [ ListEval(exprlist, μ) | μ in Ψ ]
  F(Ψ) = func(M(Ψ), scalarvals), for non-DISTINCT
  F(Ψ) = func(Dedup(M(Ψ)), scalarvals), for DISTINCT

其中 Dedup(M(Ψ)) 是序列 M(Ψ) 的一个保持顺序、无重复的版本;也就是说, Dedup(M(Ψ)) 是一个列表序列,具有以下 四个性质 (该序列中的每个这种列表都可能包含 RDF 项和 错误,因为它是由 ListEval 函数产生的)。

  1. 对于 M(Ψ) 中的每个列表 L,Dedup(M(Ψ)) 中都存在一个 列表 L',使得 LL' 相同, 其中 M(Ψ) 中两个列表 LL' 的 相同关系按照 Group 运算符定义中指定的方式确定。
  2. 对于 Dedup(M(Ψ)) 中的每个列表 L,M(Ψ) 中都存在 一个列表 L',使得 LL' 相同。
  3. Dedup(M(Ψ)) 不含重复项。也就是说,对于每两个自然数 ij,只要 ij, Dedup(M(Ψ)) 中第 i 个 位置的列表就不是与第 j 个位置的列表相同的列表。
  4. 对于 Dedup(M(Ψ)) 中任意两个列表 L1L2, 它们在 M(Ψ) 中首次出现的相对顺序会 保留在 Dedup(M(Ψ)) 中。也就是说,如果 i1 < i2,则 j1 < j2,其中
    • i1 是使得 L1 位于 M(Ψ) 中第 i1 个位置的最小自然数,
    • i2 是使得 L2 位于 M(Ψ) 中第 i2 个位置的最小自然数,
    • j1L1 在 Dedup(M(Ψ)) 中的位置,并且
    • j2L2 在 Dedup(M(Ψ)) 中的位置。

特殊情形:COUNT 与表达式 * 一起使用时,F(Ψ) 是组解序列的基数, 即 F(Ψ) = Card(Ψ), 或者如果存在 DISTINCT 关键字,则 F(Ψ) = Card(Distinct(Ψ))。

scalarvals 用于把值传递给底层集合函数,绕过 分组机制。例如,聚合表达式 GROUP_CONCAT(?x ; separator="|") 具有一个 scalarvals 参数 { "separator" → "|" }。

所有聚合都可以在其参数列表的第一个 token 处使用 DISTINCT 关键字。如果存在此关键字,则传给 func 的 第一个参数是 Dedup(M(Ψ))。

示例

给定具有以下值的解序列 Ψ

solution ?x ?y ?z
μ1 1 2 3
μ2 1 3 4
μ3 2 5 6

以及查询表达式 SELECT (ex:agg(?y, ?z) AS ?agg) WHERE { ?x ?y ?z } GROUP BY ?x。

我们产生 G = Group((?x), Ψ) = { (1) → [μ1, μ2], (2) → [μ3] }

因此 Aggregation((?y, ?z), ex:agg, {}, G) =
{ ((1), eg:agg([(2, 3), (3, 4)], {})), ((2), eg:agg([(5, 6)], {})) }。

定义:AggregateJoin

S1, ..., Sn 为集合列表,其中 每个集合 Si 都包含由 Aggregation 产生的从键到(聚合)值的映射。

K = { key | key in dom(Sj) for some 1 ≤ jn } 为键的 集合,则
AggregateJoin(S1, ..., Sn) = { agg1val1, ..., aggnvaln | key in K and keyvali in Si for each 1 ≤ in }

18.6.1.1 集合函数

SPARQL 聚合底层的集合函数都具有共同的签名: SetFunc(S),或 SetFunc(S, scalarvals),其中 S 是 列表序列,而 scalarvals 是 一个或多个标量值,它们通过 SPARQL 文法中聚合的 ( ... ; key=value ) 语法间接传递给集合函数。SPARQL Query 1.1 中内置聚合 支持的此功能唯一用途是 GROUP_CONCAT, 如 GROUP_CONCAT(?x ; separator=", ")

请注意,名称 “Set Function” 有一定历史原因——传给集合 函数的参数实际上是序列。由于它与 SQL Set Functions 的共同性,该名称被保留下来,SQL Set Functions 作用于多重集。

本文档中定义的集合函数是 CountSumMinMaxAvgGroupConcatSample ——分别对应聚合 COUNTSUMMINMAXAVGGROUP_CONCATSAMPLE。定义见 以下各节。系统可以选择使用本地扩展来扩展此集合,使用与函数和转换相同的记法。 注意,除非使用 ; separator, 否则这要求解析器在判断使用聚合的查询中是否存在任何错误之前, 先知道某个 IRI 是指函数、转换还是 聚合。

以下各节中集合函数的定义 基于两个函数:FlattenCard,它们定义如下。

Flatten 是一个函数,用于 将列表序列折叠为单个列表。 例如,[(1, 2), (3, 4)] 会变成 (1, 2, 3, 4)。

定义:Flatten

S 为列表序列, 即 S = [L1, L2, ..., Lm], 其中,对于每个 i ∈ {1, ..., m}, Li 是一个列表。

Flatten(S) 是列表 ( x | L in S and x in L )。

Card 是一个函数,返回 一个序列或元素列表的基数(这些元素可以是 解映射,也可以是其他类型的元素,具体取决于 上下文)。

定义:Card

给定一个序列或列表 LCard(L) 是 L 的基数。

18.6.1.2 Count

Count 是一个 SPARQL 集合函数,用于计数 给定表达式在聚合组中 具有已绑定、非错误值的次数。

定义:Count

xsd:integer Count(sequence S)

Count(S) = Card(L'),

其中 L' 是列表 L = Flatten(S) 移除所有错误元素后的结果。

18.6.1.3 Sum

Sum 是一个 SPARQL 集合函数,返回通过对 聚合组内的值求和而获得的数值。 类型提升按照 op:numeric-add 函数发生,并以传递方式应用 (见下方定义),因此在 ?x 具有值 1 (integer)、2.0e0 (float) 和 3.0 (decimal) 的聚合组中,SUM(?x) 的值将为 6.0 (float)。

定义:Sum

numeric Sum(sequence S)

Sum(S) = SumList(L),

其中 L = Flatten(S),并且 SumList(L) 按如下方式递归定义。

注意,L1L 中的第一个元素,而 L2..n 是移除 其第一个元素后的 L

以这种方式,Sum( [(1), (2), (3)] ) = SumList( (1, 2, 3) ) = op:numeric-add(1, op:numeric-add(2, op:numeric-add(3, 0)))。

18.6.1.4 Avg
Avg 集合函数 计算组中某个表达式的 平均值。它以 Sum 和 Count 定义。

定义:Avg

numeric Avg(sequence S)

如果 Count(S) = 0, 则 Avg(S) = "0"^^xsd:integer

如果 Count(S) > 0, 则 Avg(S) = Sum(S) / Count(S)。

例如,Avg([(1), (2), (3)]) = Sum([(1), (2), (3)])/Count([(1), (2), (3)]) = 6/3 = 2。

18.6.1.5 Min

Min 是一个 SPARQL 集合函数,分别返回组中的 最小值。

它使用 SPARQL ORDER BY 排序定义,以允许对 任意类型表达式进行排序。

定义:Min

RDFterm Min(sequence S)

Min(S) = MinList(L),

其中 L 是通过 Flatten(S) 获得, 并随后按照 ORDER BY ASC 子句排序的值列表, 而 MinList(L) 定义如下。

  • 如果 Card(L) = 0,则 MinList(L) = error。
  • 如果 Card(L) > 0,则 MinList(L) = L1, 其中 L1L 中的第一个元素。
18.6.1.6 Max

Max 是一个 SPARQL 集合函数,分别返回组中的 最大值。

它使用 SPARQL ORDER BY 排序定义,以允许对 任意类型表达式进行排序。

定义:Max

RDFterm Max(sequence S)

Max(S) = MaxList(L),

其中 L 是通过 Flatten(S) 获得, 并随后按照 ORDER BY DESC 子句排序的值列表, 而 MaxList(L) 定义如下。

  • 如果 Card(L) = 0,则 MaxList(L) = error。
  • 如果 Card(L) > 0,则 MaxList(L) = L1, 其中 L1L 中的第一个元素。
18.6.1.7 GroupConcat

GroupConcat 是一个集合函数,它对 某个表达式在一个组中的值执行字符串连接。字符串的顺序未指定。 连接中使用的分隔符字符可以通过标量参数 SEPARATOR 给出。

定义:GroupConcat

xsd:string GroupConcat(sequence S, function scalarvals)

如果 GROUP_CONCAT 中不存在 scalarvals 参数, 则 scalarvals 被视为空函数。

sep 为按如下方式定义的字符串。

  • 如果 scalarvals 对参数 "separator" 有定义, 则 sep = scalarvals("separator")。
  • 如果 scalarvals 对参数 "separator" 未定义, 则 sep 是 “space” 字符(即 unicode 码位 U+0020)。

GroupConcat(S, scalarvals) = GCList(L, sep),

其中 L = Flatten(S) 且 GCList(L, sep) 按如下方式递归定义。

  • 如果 Card(L) = 0,则 GCList(L, sep) = ""。
  • 如果 Card(L) = 1,则 GCList(L, sep) = CONCAT("", L1)。
  • 如果 Card(L) > 1,则 GCList(L, sep) = CONCAT(L1, sep, GCList(L2..n, sep))。

注意,L1L 中的第一个元素,而 L2..n 是移除 其第一个元素后的 L

例如,GroupConcat([("a"), ("b"), ("c")], {"separator" → "."}) = GCList( ("a", "b", "c"), "." ) = "a.b.c"。

18.6.1.8 Sample

Sample 是一个集合函数,它从传给它的序列中 返回一个任意值。

定义:Sample

RDFterm Sample(sequence S)

如果 Card(S) = 0,则 Sample(S) = error。

如果 Card(S) > 0,则 Sample(S) = v,其中 v in Flatten(S)。

例如,给定 Sample([("a"), ("b"), ("c")]), "a"、"b" 和 "c" 都是有效的返回 值。注意,对于给定输入,Sample 函数不 要求是确定性的。唯一限制是输出值必须存在于输入序列中。

18.6.2 求值语义

我们定义 eval(D(G), AQE, μctx),作为 一个代数查询表达式 AQE 的求值, 该求值相对于具有活动图 G数据集 D, 并与解映射 μctx 相关。

活动图初始为 D 的默认图,并且 μctx 初始为空解映射 μ0

μctx 可能不同于 μ0 的情形, 是在对形式为 EXISTS { pattern }NOT EXISTS { pattern }表达式求值时, 如17.4.1.4 NOT EXISTS 与 EXISTS中所定义。

以下定义中使用的其他符号为:

Issue 225:eval 函数未针对解映射的多重集和 序列定义 spec:bug
本节中的定义没有涵盖 AQE 是解映射序列或多重集的情形。

定义:基本图 模式的求值

eval( D(G), BGP, μctx ) = 解映射多重集

基本图模式一节

定义:属性路径 模式的求值

eval( D(G), Path(X, path, Y), μctx ) = 解映射多重集

属性路径模式一节

定义:ContextSolution 的求值

eval( D(G), ContextSolution, μctx ) = 只包含 μctx、且 重数为 1 的多重集

定义:Filter 的求值

eval( D(G), Filter(F, A), μctx ) = Filter( F, eval(D(G), A, μctx), D, G )

定义:Join 的求值

eval( D(G), Join(A1, A2), μctx ) = Join( eval(D(G), A1, μctx), eval(D(G), A2, μctx) )

定义:LeftJoin 的求值

eval( D(G), LeftJoin(A1, A2, F), μctx ) = LeftJoin( eval(D(G), A1, μctx), eval(D(G), A2, μctx), F, D, G )

定义:Minus 的求值

eval( D(G), Minus(A1, A2), μctx ) = Minus( eval(D(G), A1, μctx), eval(D(G), A2, μctx) )

定义:Union 的求值

eval( D(G), Union(A1, A2), μctx ) = Union( eval(D(G), A1, μctx), eval(D(G), A2, μctx) )

定义:Graph 的求值

对于每个 x,如果它是 一个 IRI 或 一个变量eval( D(G), Graph(x, A), μctx ) 定义如下:

  • 如果 x 是一个 IRI, 且它是 D 中的图名
    eval( D(G), Graph(x, A), μctx ) = eval( D(Gx), A, μctx ),
    其中 GxD 中名称为 x 的命名图的 RDF 图。
  • 如果 x 是一个 IRI, 且它不是 D 中的图名
    eval( D(G), Graph(x, A), μctx ) 为空多重集。
  • 如果 x 是一个变量,
    eval( D(G), Graph(x, A), μctx ) = Ω
    其中 Ω 是由以下算法产生的解映射多重集:
    Ω := the empty multiset
    for each graph name gn in D (recall that a graph name may be an IRI or a blank node)
        G' := the RDF graph of the named graph with name gn in D
        Ω' := eval( D(G'), A, μctx )
        Ω := Union( Ω, Join(Ω', μ) ), where μ = {xgn}
    the result is Ω
定义:Group 的求值

eval( D(G), Group(exprlist, A), μctx ) = Group( exprlist, eval(D(G), A, μctx) )

定义:Aggregation 的求值

eval( D(G), Aggregation(exprlist, func, scalarvals, Grp), μctx ) = Aggregation( exprlist, func, scalarvals, eval(D(G), Grp, μctx) )

定义:AggregateJoin 的求值

eval( D(G), AggregateJoin(A1, ..., An), μctx ) = AggregateJoin( eval(D(G), A1, μctx), ..., eval(D(G), An, μctx) )

注意,如果 eval(D(G), Ai, μctx) 是一个错误,则会忽略它。

定义:Extend 的求值

eval( D(G), Extend(A, var, expr), μctx ) = Extend( eval(D(G), A, μctx), var, expr, D, G )

定义:ToList 的求值

eval( D(G), ToList(A), μctx ) = ToList( eval(D(G), A, μctx) )

定义:Distinct 的求值

eval( D(G), Distinct(A), μctx ) = Distinct( eval(D(G), A, μctx) )

定义:Reduced 的求值

eval( D(G), Reduced(A), μctx ) = Reduced( eval(D(G), A, μctx) )

定义:Project 的求值

eval( D(G), Project(A, vars), μctx ) = Project( eval(D(G), A, μctx), vars )

定义:OrderBy 的求值

eval( D(G), OrderBy(A, condition), μctx ) = OrderBy( eval(D(G), A, μctx), condition )

定义:ToMultiSet 的求值

eval( D(G), ToMultiset(A), μctx ) = ToMultiSet( eval(D(G), A, μctx) )

定义:Slice 的求值

eval( D(G), Slice(A, offset), μctx ) = Slice( eval(D(G), A, μctx), offset )

eval( D(G), Slice(A, offset, limit), μctx ) = Slice( eval(D(G), A, μctx), offset, limit )

18.6.3 扩展 SPARQL 基本图匹配

SPARQL 的整体设计可用于假定一种比简单蕴涵更复杂的 蕴涵形式的查询,方法是重写基本图 模式的匹配条件。由于以一种适用于所有蕴涵形式并能最优消除无用或 不适当冗余的通用形式陈述这些条件仍是一个开放研究问题, 本文档只给出任何此类解决方案都应满足的必要条件。这些条件需要针对 每个具体情形扩展为完整定义。

基本图模式与三元组模式之间的关系,和 RDF 图与 RDF 三元组之间的关系相同,并且许多相同术语都可应用于它们。 特别是,如果存在一个在三元组模式的项之间的双射 M,它把空白节点映射到空白节点, 并把变量、字面量和 IRI 映射到自身,使得一个三元组 ( s, p, o ) 在第一个模式中,当且仅当三元组 ( M(s), M(p), M(o) ) 在第二个模式中, 则称两个基本图模式是等价的。此定义把 RDF 图等价性的定义扩展到 基本图模式,方式是在等价模式之间保留变量名。

蕴涵体制指定

  1. 称为该体制下良构的一组 RDF 图子集
  2. 良构图子集与良构图之间的蕴涵关系。

关于查询各种蕴涵体制的详细定义可见 SPARQL 1.1 蕴涵体制

某些蕴涵体制可以把某些 RDF 图归类为不一致。例如,RDF 图:

_:x rdf:type xsd:string .
_:x rdf:type xsd:decimal .

当 D 包含 XSD 数据类型时,它是 D-不一致的。对不一致图进行查询的效果 不由本规范涵盖,而必须由具体的 SPARQL 扩展来指定。

蕴涵体制 E 必须为基本图模式求值提供条件, 使得对于任何基本图模式 BGP、任何 RDF 图 G,以及任何满足 这些条件的求值,所得解多重集都能在 RDF 图 等价意义下唯一确定。我们用 Eval-E(G, BGP) 表示使用 E 对 G 上的 BGP 求值所得的解多重集。
蕴涵体制还必须满足以下条件:

  1. 对于任何 E-一致的活动图 AG,蕴涵体制 E 唯一指定一个 与 AG E-等价的作用域图 SG。
  2. 为 E 指定一组良构图,使得对于任何基本图模式 BGP、作用域图 SG,以及 Eval-E(SG, BGP) 中的解映射 μ,图 μ(BGP) 对 E 是良构的。
  3. 对于任何基本图模式 BGP 和作用域图 SG,如果 μ1, ..., μn in Eval-E(SG, BGP) 且 BGP1, ..., BGPn 都是与 BGP 等价、但彼此之间以及与 SG 都不共享任何空白节点的基本 图模式,则

    SG E-entails (SG union μ1(BGP1) union ... union μn(BGPn))

    这些条件并不能完全确定可能答案的集合,因为 RDF 允许无限量的冗余。因此,还必须满足以下条件。

  4. 蕴涵体制应该根据体制需要提供条件,以防止平凡的无限解 多重集。
18.6.3.1

(a) SG 通常会与 AG 图等价,但将其限制为 E-等价 允许在查询之前对源文档应用某些形式的规范化, 例如消除语义冗余。

(b) 条件 3 中的构造确保由解映射引入的任何空白节点 都以一种与 SG 中空白节点出现方式内部一致的方式使用。 这确保只有当在一个答案集中多于一个答案中出现的空白节点标识符 确实在 SG 中标识相同空白节点时,才会发生这种情况。 如果该扩展不允许绑定到空白节点,则此条件可以 简化为以下条件:

SG E-entails μ(BGP) for each solution mapping μ.

(c) 这些条件并未施加 SPARQL 关于 SG 不与 AG 或 BGP 共享 空白节点的要求。特别是,它允许 SG 实际上就是 AG。这允许 空白节点标识符在查询和源文档之间,或跨多个查询保留其含义的 查询协议。然而,当前的 SPARQL 协议规范并不支持此类协议。

(d) 由于条件 1 到 3 只是答案的必要条件,条件 4 允许合法答案集合可以以各种方式受到限制的情形。

(e) 这些条件都没有显式提及 BGP 中空白节点上的实例映射。 对于某些蕴涵体制,空白节点的存在性解释不能通过单个实例映射的存在 完全捕获。这些条件允许此类体制对查询模式中的空白节点赋予 “完全存在性”的解读。

很容易证明,对于 E 为简单蕴涵的情形,SPARQL 满足这些条件, 因为 SPARQL 关于 SG 的条件是它与 AG 图等价,但不与 AG 或 BGP 共享 空白节点(这满足第一个条件)。唯一非平凡的条件是 (3)。

对于每个解映射 μi,根据基本图 模式匹配的定义,存在一个 RDF 实例映射 σi,使得 Pi(BGPi) 是 SG 的子图,其中 Pi 是由 μi 和 σi 组合而成的模式 实例映射。由于 BGPi 和 SG 没有共同的空白节点,σi 和 μi 的值域 不包含来自 BGPi 的空白节点;因此,解映射 μi 和 Pi 的 RDF 实例映射 σi 可交换,所以 Pi(BGPi) = σii(BGPi))。因此

P1(BGP1) union ... union Pn(BGPn)
= σ11(BGP1)) union ... union σnn(BGPn))
= [ σ1 + ... + σn]( μ1(BGP1) union ... union μn(BGPn) )

因为 σi RDF 实例映射的定义域全都彼此 互不相交。由于它们也与 SG 不相交,

SG union [ σ1 + ... + σn]( μ1(BGP1) union ... union μn(BGPn) )
= [ σ1 + ... + σn](SG union μ1(BGP1) union ... union μn(BGPn) )

SG union μ1(BGP1) union ... union μn(BGPn)

具有一个是 SG 子图的实例,因此根据 RDF 插值引理 [RDF12-SEMANTICS],它被 SG 简单蕴涵。

19. SPARQL 文法

SPARQL 文法涵盖 SPARQL Query 和 SPARQL 1.1 Update

19.1 SPARQL 字符串

SPARQL 字符串是一个 RDF 字符串,它 符合本节给出的文法。

RDF 字符串是 一个由 Unicode 码位 构成的序列,这些码位是 Unicode 标量值。 Unicode 标量值不包括 代理码位

SPARQL 查询字符串是一个 SPARQL 字符串,它符合从 QueryUnit 产生式开始的文法。

SPARQL 更新字符串是一个 SPARQL 字符串,它符合从 UpdateUnit 产生式开始的文法。

为了与未来版本的 Unicode 兼容,此字符串中的字符可以 包含在本出版物发布之日尚未分配的 Unicode 码位(见 Unicode Identifiers and Syntax [UAX31] 第 4 节 Pattern Syntax)。对于 带有排除字符 类的产生式(例如 [^<>'{}|^`]),字符从 范围 #x0 - #x10FFFF 中排除。

19.2 转义序列

SPARQL 文档中使用三种形式的转义:

转义序列可以用于以下位置:

数值
转义
字符串
转义
保留字符
转义
IRI, 用作 RDF 项 或用于 PREFIXBASE 声明
局部名称
字符串

转义序列通过取得与相关文法产生式匹配的 Unicode 码位序列, 然后应用以下步骤进行处理。

  1. 从左到右扫描 Unicode 码位序列,以寻找 第一个匹配的转义序列。
  2. 当找到转义序列时,将与该转义序列对应的码位 替换该转义序列。
  3. Unicode 码位序列的扫描从被替换转义序列之后 紧接的码位继续。
已处理转义序列的示例
输入码位 输出码位 码位数量
abc\u005Cdef abc\def 7
abc\u005Ctuv abc\tuv 7
\u005CA \A 2
\\u005C \u005C 6
\u005C\u005C \\ 2
\\\u005C \\ 2
\\\\ \\ 2
\u005Cn \n 2

%-编码序列位于 IRI 的字符范围内, 并且在局部名称中被显式允许。 它们表现为一个 % 后跟两个十六进制字符,并表示 相同的三个字符序列。这些序列在处理期间不会 被解码。 在 Turtle 中写作 <http://a.example/%66oo-bar> 的项指示 IRI http://a.example/%66oo-bar, 而不是 IRI http://a.example/foo-bar。 使用前缀 PREFIX ex: <http://a.example/> 写作 ex:%66oo-bar 的项 也指示 IRI http://a.example/%66oo-bar

19.3 空白

空白(产生式 WS)用于分隔两个 否则会被(错误)识别为一个终结符的终结符。下面规则名中 大写的名称表示空白具有意义的位置;这些规则构成一种可用于构造 SPARQL 解析器的终结符选择。空白在字符串中有意义。 否则,token 之间的空白会被忽略。

例如:

?a<?b&&?c>?d

是 token 序列:变量 '?a'、IRI '<?b&&?c>' 以及变量 '?d',而不是一个 使用运算符 '&&' 连接两个表达式、并使用 '<'(小于)和 '>'(大于)的表达式。

19.4 注释

SPARQL 查询中的注释采用 '#' 的形式,位于 IRI 或字符串之外, 并持续到行尾(由字符 0x0D0x0A 标记)或文件结尾(如果注释标记之后没有行尾)。 注释被视为空白。

19.5 IRI 引用

IRIREF 产生式和 PrefixedName(前缀展开之后)产生式匹配的文本, 在转义处理之后,必须符合 RFC 3987 “ABNF for IRI References and IRIs” 第 2.2 节中 IRI 引用的通用语法 [RFC3987]。 例如, IRIREF <abc#def> 可以出现在 SPARQL 查询字符串中,但 IRIREF <abc##def> 不得出现。

使用 BASE 关键字声明的基 IRI 必须是绝对 IRI。使用 PREFIX 关键字声明的前缀不得在 同一查询中重新声明。关于 BASEPREFIX 的说明,见第 4.1.1 节 IRI 项语法

19.6 空白节点和 空白节点标识符

空白节点不能用于:

SPARQL 更新 请求中。

空白节点标识符 的作用域限定在其出现所在的 SPARQL 字符串内。 在同一请求字符串中对同一空白节点标识符的不同使用 指向同一个空白节点。每个请求都会生成新的空白节点; 不能跨请求通过标识符引用空白节点。

同一空白节点标识符不能用于:

注意,同一空白节点标识符可以出现在 SPARQL 1.1 Update 请求中的不同 QuadPattern 子句中。

19.7 文法

文法中使用的 EBNF 记法定义于 Extensible Markup Language (XML) 1.1 [XML11] 第 6 节 Notation

文法有两个入口点:

  1. 用于 SPARQL 查询语言的 QueryUnit
  2. 用于 SPARQL 更新语言的 UpdateUnit

当使用名称为大写的规则作为终结符时,SPARQL 文法是 LL(1)。

注:

  1. 关键字以大小写不敏感的方式匹配,但关键字 'a' 除外; 按照 Turtle,它用于 代替 rdf:type 的 IRI (完整形式为 http://www.w3.org/1999/02/22-rdf-syntax-ns#type)。
  2. 转义序列区分大小写。
  3. 在对输入进行 token 化并选择文法规则时,选择最长匹配。
  4. 在带符号数字中,符号和数字之间不允许有空白。 AdditiveExpression 文法规则通过覆盖表达式后跟带符号数字的两种情形来允许这一点。 这些情形会根据需要产生对无符号数字的加法或减法。
  5. token INSERT DATADELETE DATADELETE WHERE 允许两个词之间有任意数量的空白。 为清晰起见,文法中使用单空格版本。
  6. QuadDataQuadPattern 规则都使用规则 Quads。用于 INSERT DATADELETE DATA 的规则 QuadData 不得允许 quad 模式中出现变量。
  7. 空白节点语法不允许用于 DELETE WHEREDELETEDeleteClause, 也不允许用于 DELETE DATA
  8. 限制空白节点标识符使用的规则见 19.6 空白节点和空白节点 标识符
  9. VALUES 子句的 变量列表中的变量数量, 必须对应于 RDF 项DataBlock 中每个关联值列表中的数量。
  10. VALUES 子句的 变量列表中的变量在该列表内必须唯一。
  11. SELECT 子句中由 AS 引入的变量不得已经在作用域内
  12. BIND 子句中被赋值的变量, 不得已经在 GroupGraphPattern 内紧邻其前的 TriplesBlock 中被使用。
  13. 聚合函数可以是 聚合的内置关键字之一, 或者是自定义聚合,它在语法上是一个函数 调用。聚合函数只能在 SELECTHAVINGORDER BY 子句中使用。
  14. 聚合函数的表达式参数不能 包含聚合函数。
  15. 只有自定义聚合函数可以在 函数调用中使用 DISTINCT 关键字。
  16. reifierannotation 语法 只允许在属性位置是简单路径(IRI、关键字 a 或变量)时 出现在三元组之后, 而不允许用于其他路径表达式。
  17. 在包含 GROUP BY 子句的查询中, 或者当 聚合 出现在 HAVINGORDER BY 子句中时, 不允许在 SELECT 子句中使用 *
[1]   QueryUnit   ::=   Query
[2]   Query   ::=   Prologue
( SelectQuery | ConstructQuery | DescribeQuery | AskQuery )
ValuesClause
[3]   UpdateUnit   ::=   Update
[4]   Prologue   ::=   ( BaseDecl | PrefixDecl | VersionDecl )*
[5]   BaseDecl   ::=   'BASE' IRIREF
[6]   PrefixDecl   ::=   'PREFIX' PNAME_NS IRIREF
[7]   VersionDecl   ::=   'VERSION' VersionSpecifier
[8]   VersionSpecifier   ::=   STRING_LITERAL1 | STRING_LITERAL2
[9]   SelectQuery   ::=   SelectClause DatasetClause* WhereClause SolutionModifier
[10]   SubSelect   ::=   SelectClause WhereClause SolutionModifier ValuesClause
[11]   SelectClause   ::=   'SELECT' ( 'DISTINCT' | 'REDUCED' )? ( ( Var | ( '(' Expression 'AS' Var ')' ) )+ | '*' )
[12]   ConstructQuery   ::=   'CONSTRUCT' ( ConstructTemplate DatasetClause* WhereClause SolutionModifier | DatasetClause* 'WHERE' ConstructTemplate SolutionModifier )
[13]   DescribeQuery   ::=   'DESCRIBE' ( VarOrIri+ | '*' ) DatasetClause* WhereClause? SolutionModifier
[14]   AskQuery   ::=   'ASK' DatasetClause* WhereClause SolutionModifier
[15]   DatasetClause   ::=   'FROM' ( DefaultGraphClause | NamedGraphClause )
[16]   DefaultGraphClause   ::=   SourceSelector
[17]   NamedGraphClause   ::=   'NAMED' SourceSelector
[18]   SourceSelector   ::=   iri
[19]   WhereClause   ::=   'WHERE'? GroupGraphPattern
[20]   SolutionModifier   ::=   GroupClause? HavingClause? OrderClause? LimitOffsetClauses?
[21]   GroupClause   ::=   'GROUP' 'BY' GroupCondition+
[22]   GroupCondition   ::=   BuiltInCall | FunctionCall | '(' Expression ( 'AS' Var )? ')' | Var
[23]   HavingClause   ::=   'HAVING' HavingCondition+
[24]   HavingCondition   ::=   Constraint
[25]   OrderClause   ::=   'ORDER' 'BY' OrderCondition+
[26]   OrderCondition   ::=   ( ( 'ASC' | 'DESC' ) BrackettedExpression )
| ( Constraint | Var )
[27]   LimitOffsetClauses   ::=   LimitClause OffsetClause? | OffsetClause LimitClause?
[28]   LimitClause   ::=   'LIMIT' INTEGER
[29]   OffsetClause   ::=   'OFFSET' INTEGER
[30]   ValuesClause   ::=   ( 'VALUES' DataBlock )?
[31]   Update   ::=   Prologue ( Update1 ( ';' Update )? )?
[32]   Update1   ::=   Load | Clear | Drop | Add | Move | Copy | Create | DeleteWhere | Modify | InsertData | DeleteData
[33]   Load   ::=   'LOAD' 'SILENT'? iri ( 'INTO' GraphRef )?
[34]   Clear   ::=   'CLEAR' 'SILENT'? GraphRefAll
[35]   Drop   ::=   'DROP' 'SILENT'? GraphRefAll
[36]   Create   ::=   'CREATE' 'SILENT'? GraphRef
[37]   Add   ::=   'ADD' 'SILENT'? GraphOrDefault 'TO' GraphOrDefault
[38]   Move   ::=   'MOVE' 'SILENT'? GraphOrDefault 'TO' GraphOrDefault
[39]   Copy   ::=   'COPY' 'SILENT'? GraphOrDefault 'TO' GraphOrDefault
[40]   InsertData   ::=   'INSERT DATA' QuadData
[41]   DeleteData   ::=   'DELETE DATA' QuadData
[42]   DeleteWhere   ::=   'DELETE WHERE' QuadPattern
[43]   Modify   ::=   ( 'WITH' iri )? ( DeleteClause InsertClause? | InsertClause ) UsingClause* 'WHERE' GroupGraphPattern
[44]   DeleteClause   ::=   'DELETE' QuadPattern
[45]   InsertClause   ::=   'INSERT' QuadPattern
[46]   UsingClause   ::=   'USING' ( iri | 'NAMED' iri )
[47]   GraphOrDefault   ::=   'DEFAULT' | 'GRAPH'? iri
[48]   GraphRef   ::=   'GRAPH' iri
[49]   GraphRefAll   ::=   GraphRef | 'DEFAULT' | 'NAMED' | 'ALL'
[50]   QuadPattern   ::=   '{' Quads '}'
[51]   QuadData   ::=   '{' Quads '}'
[52]   Quads   ::=   TriplesTemplate? ( QuadsNotTriples '.'? TriplesTemplate? )*
[53]   QuadsNotTriples   ::=   'GRAPH' VarOrIri '{' TriplesTemplate? '}'
[54]   TriplesTemplate   ::=   TriplesSameSubject ( '.' TriplesTemplate? )?
[55]   GroupGraphPattern   ::=   '{' ( SubSelect | GroupGraphPatternSub ) '}'
[56]   GroupGraphPatternSub   ::=   TriplesBlock? ( GraphPatternNotTriples '.'? TriplesBlock? )*
[57]   TriplesBlock   ::=   TriplesSameSubjectPath ( '.' TriplesBlock? )?
[58]   ReifiedTripleBlock   ::=   ReifiedTriple PropertyList
[59]   ReifiedTripleBlockPath   ::=   ReifiedTriple PropertyListPath
[60]   GraphPatternNotTriples   ::=   GroupOrUnionGraphPattern | OptionalGraphPattern | MinusGraphPattern | GraphGraphPattern | ServiceGraphPattern | Filter | Bind | InlineData
[61]   OptionalGraphPattern   ::=   'OPTIONAL' GroupGraphPattern
[62]   GraphGraphPattern   ::=   'GRAPH' VarOrIri GroupGraphPattern
[63]   ServiceGraphPattern   ::=   'SERVICE' 'SILENT'? VarOrIri GroupGraphPattern
[64]   Bind   ::=   'BIND' '(' Expression 'AS' Var ')'
[65]   InlineData   ::=   'VALUES' DataBlock
[66]   DataBlock   ::=   InlineDataOneVar | InlineDataFull
[67]   InlineDataOneVar   ::=   Var '{' DataBlockValue* '}'
[68]   InlineDataFull   ::=   ( NIL | '(' Var* ')' ) '{' ( '(' DataBlockValue* ')' | NIL )* '}'
[69]   DataBlockValue   ::=   iri | RDFLiteral | NumericLiteral | BooleanLiteral | 'UNDEF' | TripleTermData
[70]   Reifier   ::=   '~' VarOrReifierId?
[71]   VarOrReifierId   ::=   Var | iri | BlankNode
[72]   MinusGraphPattern   ::=   'MINUS' GroupGraphPattern
[73]   GroupOrUnionGraphPattern   ::=   GroupGraphPattern ( 'UNION' GroupGraphPattern )*
[74]   Filter   ::=   'FILTER' Constraint
[75]   Constraint   ::=   BrackettedExpression | BuiltInCall | FunctionCall
[76]   FunctionCall   ::=   iri ArgList
[77]   ArgList   ::=   NIL | '(' 'DISTINCT'? Expression ( ',' Expression )* ')'
[78]   ExpressionList   ::=   NIL | '(' Expression ( ',' Expression )* ')'
[79]   ConstructTemplate   ::=   '{' ConstructTriples? '}'
[80]   ConstructTriples   ::=   TriplesSameSubject ( '.' ConstructTriples? )?
[81]   TriplesSameSubject   ::=   VarOrTerm PropertyListNotEmpty | TriplesNode PropertyList | ReifiedTripleBlock
[82]   PropertyList   ::=   PropertyListNotEmpty?
[83]   PropertyListNotEmpty   ::=   Verb ObjectList ( ';' ( Verb ObjectList )? )*
[84]   Verb   ::=   VarOrIri | 'a'
[85]   ObjectList   ::=   Object ( ',' Object )*
[86]   Object   ::=   GraphNode Annotation
[87]   TriplesSameSubjectPath   ::=   VarOrTerm PropertyListPathNotEmpty | TriplesNodePath PropertyListPath | ReifiedTripleBlockPath
[88]   PropertyListPath   ::=   PropertyListPathNotEmpty?
[89]   PropertyListPathNotEmpty   ::=   ( VerbPath | VerbSimple ) ObjectListPath ( ';' ( ( VerbPath | VerbSimple ) ObjectListPath )? )*
[90]   VerbPath   ::=   Path
[91]   VerbSimple   ::=   Var
[92]   ObjectListPath   ::=   ObjectPath ( ',' ObjectPath )*
[93]   ObjectPath   ::=   GraphNodePath AnnotationPath
[94]   Path   ::=   PathAlternative
[95]   PathAlternative   ::=   PathSequence ( '|' PathSequence )*
[96]   PathSequence   ::=   PathEltOrInverse ( '/' PathEltOrInverse )*
[97]   PathElt   ::=   PathPrimary PathMod?
[98]   PathEltOrInverse   ::=   PathElt | '^' PathElt
[99]   PathMod   ::=   '?' | '*' | '+'
[100]   PathPrimary   ::=   iri | 'a' | '!' PathNegatedPropertySet | '(' Path ')'
[101]   PathNegatedPropertySet   ::=   PathOneInPropertySet | '(' ( PathOneInPropertySet ( '|' PathOneInPropertySet )* )? ')'
[102]   PathOneInPropertySet   ::=   iri | 'a' | '^' ( iri | 'a' )
[103]   TriplesNode   ::=   Collection | BlankNodePropertyList
[104]   BlankNodePropertyList   ::=   '[' PropertyListNotEmpty ']'
[105]   TriplesNodePath   ::=   CollectionPath | BlankNodePropertyListPath
[106]   BlankNodePropertyListPath   ::=   '[' PropertyListPathNotEmpty ']'
[107]   Collection   ::=   '(' GraphNode+ ')'
[108]   CollectionPath   ::=   '(' GraphNodePath+ ')'
[109]   AnnotationPath   ::=   ( Reifier | AnnotationBlockPath )*
[110]   AnnotationBlockPath   ::=   '{|' PropertyListPathNotEmpty '|}'
[111]   Annotation   ::=   ( Reifier | AnnotationBlock )*
[112]   AnnotationBlock   ::=   '{|' PropertyListNotEmpty '|}'
[113]   GraphNode   ::=   VarOrTerm | TriplesNode | ReifiedTriple
[114]   GraphNodePath   ::=   VarOrTerm | TriplesNodePath | ReifiedTriple
[115]   VarOrTerm   ::=   Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | NIL | TripleTerm
[116]   ReifiedTriple   ::=   '<<' ReifiedTripleSubject Verb ReifiedTripleObject Reifier? '>>'
[117]   ReifiedTripleSubject   ::=   Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTriple | TripleTerm
[118]   ReifiedTripleObject   ::=   Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTriple | TripleTerm
[119]   TripleTerm   ::=   '<<(' TripleTermSubject Verb TripleTermObject ')>>'
[120]   TripleTermSubject   ::=   Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTerm
[121]   TripleTermObject   ::=   Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTerm
[122]   TripleTermData   ::=   '<<(' TripleTermDataSubject ( iri | 'a' ) TripleTermDataObject ')>>'
[123]   TripleTermDataSubject   ::=   iri
[124]   TripleTermDataObject   ::=   iri | RDFLiteral | NumericLiteral | BooleanLiteral | TripleTermData
[125]   VarOrIri   ::=   Var | iri
[126]   Var   ::=   VAR1 | VAR2
[127]   Expression   ::=   ConditionalOrExpression
[128]   ConditionalOrExpression   ::=   ConditionalAndExpression ( '||' ConditionalAndExpression )*
[129]   ConditionalAndExpression   ::=   ValueLogical ( '&&' ValueLogical )*
[130]   ValueLogical   ::=   RelationalExpression
[131]   RelationalExpression   ::=   NumericExpression ( '=' NumericExpression | '!=' NumericExpression | '<' NumericExpression | '>' NumericExpression | '<=' NumericExpression | '>=' NumericExpression | 'IN' ExpressionList | 'NOT' 'IN' ExpressionList )?
[132]   NumericExpression   ::=   AdditiveExpression
[133]   AdditiveExpression   ::=   MultiplicativeExpression ( '+' MultiplicativeExpression | '-' MultiplicativeExpression | ( NumericLiteralPositive | NumericLiteralNegative ) ( ( '*' UnaryExpression ) | ( '/' UnaryExpression ) )* )*
[134]   MultiplicativeExpression   ::=   UnaryExpression ( '*' UnaryExpression | '/' UnaryExpression )*
[135]   UnaryExpression   ::=     '!' UnaryExpression
| '+' PrimaryExpression
| '-' PrimaryExpression
| PrimaryExpression
[136]   PrimaryExpression   ::=   BrackettedExpression | BuiltInCall | iriOrFunction | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprTripleTerm
[137]   ExprTripleTerm   ::=   '<<(' ExprTripleTermSubject Verb ExprTripleTermObject ')>>'
[138]   ExprTripleTermSubject   ::=   iri | Var
[139]   ExprTripleTermObject   ::=   iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprTripleTerm
[140]   BrackettedExpression   ::=   '(' Expression ')'
[141]   BuiltInCall   ::=     Aggregate
| 'STR' '(' Expression ')'
| 'LANG' '(' Expression ')'
| 'LANGMATCHES' '(' Expression ',' Expression ')'
| 'LANGDIR' '(' Expression ')'
| 'DATATYPE' '(' Expression ')'
| 'BOUND' '(' Var ')'
| 'IRI' '(' Expression ')'
| 'URI' '(' Expression ')'
| 'BNODE' ( '(' Expression ')' | NIL )
| 'RAND' NIL
| 'ABS' '(' Expression ')'
| 'CEIL' '(' Expression ')'
| 'FLOOR' '(' Expression ')'
| 'ROUND' '(' Expression ')'
| 'CONCAT' ExpressionList
| SubstringExpression
| 'STRLEN' '(' Expression ')'
| StrReplaceExpression
| 'UCASE' '(' Expression ')'
| 'LCASE' '(' Expression ')'
| 'ENCODE_FOR_URI' '(' Expression ')'
| 'CONTAINS' '(' Expression ',' Expression ')'
| 'STRSTARTS' '(' Expression ',' Expression ')'
| 'STRENDS' '(' Expression ',' Expression ')'
| 'STRBEFORE' '(' Expression ',' Expression ')'
| 'STRAFTER' '(' Expression ',' Expression ')'
| 'YEAR' '(' Expression ')'
| 'MONTH' '(' Expression ')'
| 'DAY' '(' Expression ')'
| 'HOURS' '(' Expression ')'
| 'MINUTES' '(' Expression ')'
| 'SECONDS' '(' Expression ')'
| 'TIMEZONE' '(' Expression ')'
| 'TZ' '(' Expression ')'
| 'NOW' NIL
| 'UUID' NIL
| 'STRUUID' NIL
| 'MD5' '(' Expression ')'
| 'SHA1' '(' Expression ')'
| 'SHA256' '(' Expression ')'
| 'SHA384' '(' Expression ')'
| 'SHA512' '(' Expression ')'
| 'COALESCE' ExpressionList
| 'IF' '(' Expression ',' Expression ',' Expression ')'
| 'STRLANG' '(' Expression ',' Expression ')'
| 'STRLANGDIR' '(' Expression ',' Expression ',' Expression ')'
| 'STRDT' '(' Expression ',' Expression ')'
| 'sameTerm' '(' Expression ',' Expression ')'
| 'isIRI' '(' Expression ')'
| 'isURI' '(' Expression ')'
| 'isBLANK' '(' Expression ')'
| 'isLITERAL' '(' Expression ')'
| 'isNUMERIC' '(' Expression ')'
| 'hasLANG' '(' Expression ')'
| 'hasLANGDIR' '(' Expression ')'
| RegexExpression
| ExistsFunc
| NotExistsFunc
| 'isTRIPLE' '(' Expression ')'
| 'TRIPLE' '(' Expression ',' Expression ',' Expression ')'
| 'SUBJECT' '(' Expression ')'
| 'PREDICATE' '(' Expression ')'
| 'OBJECT' '(' Expression ')'
[142]   RegexExpression   ::=   'REGEX' '(' Expression ',' Expression ( ',' Expression )? ')'
[143]   SubstringExpression   ::=   'SUBSTR' '(' Expression ',' Expression ( ',' Expression )? ')'
[144]   StrReplaceExpression   ::=   'REPLACE' '(' Expression ',' Expression ',' Expression ( ',' Expression )? ')'
[145]   ExistsFunc   ::=   'EXISTS' GroupGraphPattern
[146]   NotExistsFunc   ::=   'NOT' 'EXISTS' GroupGraphPattern
[147]   Aggregate   ::=     'COUNT' '(' 'DISTINCT'? ( '*' | Expression ) ')'
| 'SUM' '(' 'DISTINCT'? Expression ')'
| 'MIN' '(' 'DISTINCT'? Expression ')'
| 'MAX' '(' 'DISTINCT'? Expression ')'
| 'AVG' '(' 'DISTINCT'? Expression ')'
| 'SAMPLE' '(' 'DISTINCT'? Expression ')'
| 'GROUP_CONCAT' '(' 'DISTINCT'? Expression ( ';' 'SEPARATOR' '=' String )? ')'
[148]   iriOrFunction   ::=   iri ArgList?
[149]   RDFLiteral   ::=   String ( LANG_DIR | '^^' iri )?
[150]   NumericLiteral   ::=   NumericLiteralUnsigned | NumericLiteralPositive | NumericLiteralNegative
[151]   NumericLiteralUnsigned   ::=   INTEGER | DECIMAL | DOUBLE
[152]   NumericLiteralPositive   ::=   INTEGER_POSITIVE | DECIMAL_POSITIVE | DOUBLE_POSITIVE
[153]   NumericLiteralNegative   ::=   INTEGER_NEGATIVE | DECIMAL_NEGATIVE | DOUBLE_NEGATIVE
[154]   BooleanLiteral   ::=   'true' | 'false'
[155]   String   ::=   STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2
[156]   iri   ::=   IRIREF | PrefixedName
[157]   PrefixedName   ::=   PNAME_LN | PNAME_NS
[158]   BlankNode   ::=   BLANK_NODE_LABEL | ANON

终结符的产生式:

[159]   IRIREF   ::=   '<' ( [^<>"{}|^`\]-[#x00-#x20] | UCHAR ) * '>'
[160]   PNAME_NS   ::=   PN_PREFIX? ':'
[161]   PNAME_LN   ::=   PNAME_NS PN_LOCAL
[162]   BLANK_NODE_LABEL   ::=   '_:' ( PN_CHARS_U | [0-9] ) ((PN_CHARS|'.')* PN_CHARS)?
[163]   VAR1   ::=   '?' VARNAME
[164]   VAR2   ::=   '$' VARNAME
[165]   LANG_DIR   ::=   '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)* ('--' [a-zA-Z]+)?
[166]   INTEGER   ::=   [0-9]+
[167]   DECIMAL   ::=   [0-9]* '.' [0-9]+
[168]   DOUBLE   ::=   ( ([0-9]+ ('.'[0-9]*)? ) | ( '.' ([0-9])+ ) ) EXPONENT
[169]   EXPONENT   ::=   [eE] [+-]? [0-9]+
[170]   INTEGER_POSITIVE   ::=   '+' INTEGER
[171]   DECIMAL_POSITIVE   ::=   '+' DECIMAL
[172]   DOUBLE_POSITIVE   ::=   '+' DOUBLE
[173]   INTEGER_NEGATIVE   ::=   '-' INTEGER
[174]   DECIMAL_NEGATIVE   ::=   '-' DECIMAL
[175]   DOUBLE_NEGATIVE   ::=   '-' DOUBLE
[176]   STRING_LITERAL1   ::=   "'" ( ([^#x27#x5C#xA#xD]) | ECHAR | UCHAR )* "'"
[177]   STRING_LITERAL2   ::=   '"' ( ([^#x22#x5C#xA#xD]) | ECHAR | UCHAR )* '"'
[178]   STRING_LITERAL_LONG1   ::=   "'''" ( ( "'" | "''" )? ( [^'\] | ECHAR | UCHAR ) )* "'''"
[179]   STRING_LITERAL_LONG2   ::=   '"""' ( ( '"' | '""' )? ( [^"\] | ECHAR | UCHAR ) )* '"""'
[180]   ECHAR   ::=   '\' [tbnrf\"']
[181]   UCHAR   ::=   ('\u' HEX HEX HEX HEX) | ('\U' HEX HEX HEX HEX HEX HEX HEX HEX)
[182]   NIL   ::=   '(' WS* ')'
[183]   WS   ::=   #x20 | #x9 | #xD | #xA
[184]   ANON   ::=   '[' WS* ']'
[185]   PN_CHARS_BASE   ::=   [A-Z] | [a-z] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x02FF] | [#x0370-#x037D] | [#x037F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
[186]   PN_CHARS_U   ::=   PN_CHARS_BASE | '_'
[187]   VARNAME   ::=   ( PN_CHARS_U | [0-9] ) ( PN_CHARS_U | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040] )*
[188]   PN_CHARS   ::=   PN_CHARS_U | '-' | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040]
[189]   PN_PREFIX   ::=   PN_CHARS_BASE ((PN_CHARS|'.')* PN_CHARS)?
[190]   PN_LOCAL   ::=   (PN_CHARS_U | ':' | [0-9] | PLX ) ((PN_CHARS | '.' | ':' | PLX)* (PN_CHARS | ':' | PLX) )?
[191]   PLX   ::=   PERCENT | PN_LOCAL_ESC
[192]   PERCENT   ::=   '%' HEX HEX
[193]   HEX   ::=   [0-9] | [A-F] | [a-f]
[194]   PN_LOCAL_ESC   ::=   '\' ( '_' | '~' | '.' | '-' | '!' | '$' | '&' | "'" | '(' | ')' | '*' | '+' | ',' | ';' | '=' | '/' | '?' | '#' | '@' | '%' )

此文法的文本版本可在此处获得。

20. 一致性

除标记为非规范性的章节外,本规范中的所有创作指南、图表、示例和注释都是非规范性的。 本规范中的其他所有内容都是规范性的。

本文档中的关键词 MAYMUSTMUST NOTOPTIONALSHOULD 在且仅在它们以这里所示的全大写形式出现时, 应按 BCP 14 [RFC2119] [RFC8174] 中所述进行解释。

20.1 一致性

关于 SPARQL 查询字符串的一致性,见第 19 SPARQL 文法节;关于查询结果的一致性,见第 16 查询形式节。 关于 application/sparql-query 媒体类型的一致性,见第 22. 互联网媒体类型节。

本规范旨在与 SPARQL 1.1 Protocol [SPARQL11-PROTOCOL]、SPARQL 查询结果 XML 格式(第二 版) [RDF-SPARQL-XMLRES]、 SPARQL 1.1 查询结果 JSON 格式 [SPARQL11-RESULTS-JSON] 和 SPARQL 1.1 查询结果 CSV 和 TSV 格式 [SPARQL11-RESULTS-CSV-TSV] 结合使用。其一致性准则见这些规范。

注意,SPARQL 协议描述了一种把 SPARQL 查询传递给 SPARQL 查询处理服务,并把查询结果返回给请求实体的方式。

21. 互联网媒体类型和 文件扩展名

SPARQL 查询语言的互联网媒体类型(以前称为 MIME 类型)是 "application/sparql-query"。

建议 sparql 查询文件在所有平台上使用扩展名 ".rq"(小写)。

类型名称:
application
子类型名称:
sparql-query
必需参数:
可选参数:
编码考量:
SPARQL 查询语言的语法以 Unicode 码位 [UNICODE] 表达。编码始终为 UTF-8 [RFC3629]。
Unicode 码位也可以使用 \uXXXX(U+0 到 U+FFFF)或 \UXXXXXXXX 语法(U+0 到 U+10FFFF)表示,其中 X 是十六进制数字 [0-9A-Fa-f], 排除 U+D800 到 U+DFFF,即 代理码位
安全考量:
见 SPARQL Query 附录 C,安全考量,以及 UTF-8,ISO 10646 的一种转换格式 [RFC3629] 第 7 节 安全考量。
互操作性考量:
没有已知的互操作性问题。
已发布规范:
本规范。
使用此媒体类型的应用:
目前没有已知应用使用此媒体类型。
附加信息:
幻数:
SPARQL 查询可在文档开头附近包含字符串 'PREFIX'(大小写无关)。
文件扩展名:
".rq"
基 URI:
SPARQL 'BASE <IRIref>' 项可以改变查询语言中稍后在文档中按顺序使用的 相对 IRIref 的当前基 URI。
进一步信息的联系人及电子邮件地址:
public-rdf-dawg-comments@w3.org
预期用途:
COMMON
使用限制:
作者/变更控制者:
SPARQL 1.2 规范是 World Wide Web Consortium 的 RDF-star Working Group 的工作成果。W3C 对这些规范拥有变更控制权。

A. SPARQL 1.1 Query Language 与 SPARQL 1.2 Query Language 之间的变更

本节是非规范性的。

B. 隐私考量

TODO

C. 安全考量

使用 FROM、FROM NAMED 或 GRAPH 的 SPARQL 查询可能导致指定 URI 被 解引用。这可能导致额外使用网络、磁盘或 CPU 资源,并带来 拒绝服务等相关次生问题。应考虑 统一资源 标识符(URI):通用语法 [RFC3986] 第 7 节中的安全 问题。此外,在某些情况下,file: URI 的内容可能被访问、处理并作为结果返回,从而导致对本地资源的意外 访问。

SPARQL 请求可能导致从 SPARQL 端点发出额外请求,例如 FROM NAMED。 该端点可能位于组织的防火墙或 DMZ 内,因此 此类查询可能成为间接攻击的来源。

SPARQL 语言允许扩展,这些扩展会有其自身的安全 影响。

多个 IRI 可能具有相同外观。不同文字体系中的字符可能看起来 相似(西里尔字母 “о” 可能看起来类似拉丁字母 “o”)。一个字符后跟组合 字符可能与另一个字符具有相同的视觉表示(LATIN SMALL LETTER E 后跟 COMBINING ACUTE ACCENT 与 LATIN SMALL LETTER E WITH ACUTE 具有相同视觉表示)。SPARQL 用户必须谨慎构造查询,使其中的 IRI 与 数据中的 IRI 匹配。关于相似字符匹配的更多信息可见 Unicode 安全考量 [UTR36] 和 国际化 资源标识符(IRI) [RFC3987] 第 8 节。

D. 国际化 考量

TODO

E. 索引

E.1 本规范定义的术语

E.2 由引用定义的术语

F. 参考文献

F.1 规范性参考文献

[BCP47]
用于标识语言的标签。A. Phillips,编;M. Davis,编。IETF。2009 年 9 月。最佳当前实践。URL:https://www.rfc-editor.org/rfc/rfc5646
[CBD]
CBD - 简明有界描述。 Patrick Stickler, Nokia。W3C。2005 年 6 月 3 日。W3C 会员提交。URL:https://www.w3.org/Submission/CBD/
[CURIE]
CURIE 语法 1.0。Mark Birbeck;Shane McCarron。W3C。2010 年 12 月 16 日。W3C 工作组说明。URL:https://www.w3.org/TR/curie/
[I18N-GLOSSARY]
国际化术语表。 Richard Ishida;Addison Phillips。W3C。2024 年 10 月 17 日。W3C 工作组说明。URL:https://www.w3.org/TR/i18n-glossary/
[rdf-concepts]
资源描述框架(RDF):概念 与抽象语法。Graham Klyne;Jeremy Carroll。W3C。2004 年 2 月 10 日。W3C 推荐标准。URL:https://www.w3.org/TR/rdf-concepts/
[RDF-DAWG-UC]
RDF 数据访问用例和 需求。Kendall Clark。W3C。2005 年 3 月 25 日。W3C 工作草案。URL:https://www.w3.org/TR/rdf-dawg-uc/
[RDF-SPARQL-XMLRES]
SPARQL 查询结果 XML 格式(第二 版)。Dave Beckett;Jeen Broekstra。W3C。2013 年 3 月 21 日。W3C 推荐标准。 URL:https://www.w3.org/TR/rdf-sparql-XMLres/
[RDF12-CONCEPTS]
RDF 1.2 概念与抽象数据 模型。Andy Seaborne;Gregg Kellogg;Olaf Hartig;Pierre-Antoine Champin。W3C。2026 年 4 月 7 日。 W3C 候选推荐标准。URL:https://www.w3.org/TR/rdf12-concepts/
[RDF12-SEMANTICS]
RDF 1.2 语义。Peter Patel-Schneider;Enrico Franconi;Dörthe Arndt。W3C。2026 年 4 月 7 日。W3C 候选推荐标准。 URL:https://www.w3.org/TR/rdf12-semantics/
[RDF12-XML]
RDF 1.2 XML 语法。Gregg Kellogg; Jerven Bolleman。W3C。2026 年 6 月 18 日。W3C 工作草案。URL:https://www.w3.org/TR/rdf12-xml/
[RFC2119]
用于在 RFC 中表示 需求级别的关键词。S. Bradner。IETF。1997 年 3 月。最佳当前实践。URL:https://www.rfc-editor.org/rfc/rfc2119
[RFC3629]
UTF-8,ISO 10646 的一种转换格式。F. Yergeau。IETF。2003 年 11 月。互联网标准。URL:https://www.rfc-editor.org/rfc/rfc3629
[RFC3986]
统一资源标识符(URI):通用 语法。T. Berners-Lee;R. Fielding;L. Masinter。IETF。2005 年 1 月。互联网 标准。URL:https://www.rfc-editor.org/rfc/rfc3986
[RFC3987]
国际化资源标识符 (IRI)。M. Duerst;M. Suignard。IETF。2005 年 1 月。提议标准。URL:https://www.rfc-editor.org/rfc/rfc3987
[RFC4122]
通用唯一标识符(UUID)URN 命名空间。P. Leach;M. Mealling;R. Salz。IETF。2005 年 7 月。提议标准。 URL:https://www.rfc-editor.org/rfc/rfc4122
[RFC4647]
语言标签的匹配。A. Phillips,编;M. Davis,编。IETF。2006 年 9 月。最佳当前实践。URL:https://www.rfc-editor.org/rfc/rfc4647
[RFC8174]
RFC 2119 关键词中大写与小写的 歧义。B. Leiba。IETF。2017 年 5 月。最佳当前实践。URL:https://www.rfc-editor.org/rfc/rfc8174
[SPARQL-FEATURES]
SPARQL 新特性及其原理。 Kjetil Kjernsmo;Alexandre Passant。W3C。2009 年 7 月 2 日。W3C 工作草案。URL:https://www.w3.org/TR/sparql-features/
[SPARQL11-ENTAILMENT]
SPARQL 1.1 蕴涵体制。 Birte Glimm;Chimezie Ogbuji。W3C。2013 年 3 月 21 日。W3C 推荐标准。URL:https://www.w3.org/TR/sparql11-entailment/
[SPARQL11-FEDERATED-QUERY]
SPARQL 1.1 联邦 查询。Eric Prud'hommeaux;Carlos Buil Aranda。W3C。2013 年 3 月 21 日。W3C 推荐标准。URL:https://www.w3.org/TR/sparql11-federated-query/
[SPARQL11-PROTOCOL]
SPARQL 1.1 协议。Lee Feigenbaum;Gregory Williams;Kendall Clark;Elias Torres。W3C。2013 年 3 月 21 日。W3C 推荐标准。 URL:https://www.w3.org/TR/sparql11-protocol/
[SPARQL11-Query]
SPARQL 1.1 查询语言。Steven Harris;Andy Seaborne。W3C。2013 年 3 月 21 日。W3C 推荐标准。URL:https://www.w3.org/TR/sparql11-query/
[SPARQL11-RESULTS-CSV-TSV]
SPARQL 1.1 查询结果 CSV 和 TSV 格式。Andy Seaborne。W3C。2013 年 3 月 21 日。W3C 推荐标准。URL:https://www.w3.org/TR/sparql11-results-csv-tsv/
[SPARQL11-RESULTS-JSON]
SPARQL 1.1 查询结果 JSON 格式。Andy Seaborne。W3C。2013 年 3 月 21 日。W3C 推荐标准。URL:https://www.w3.org/TR/sparql11-results-json/
[SPARQL11-UPDATE]
SPARQL 1.1 更新。Paula Gearon; Alexandre Passant;Axel Polleres。W3C。2013 年 3 月 21 日。W3C 推荐标准。URL:https://www.w3.org/TR/sparql11-update/
[SPARQL12-PROTOCOL]
SPARQL 1.2 协议。Andy Seaborne;Ruben Taelman;Gregory Williams;Thomas Pellissier Tanon。W3C。2026 年 4 月 26 日。W3C 工作 草案。URL:https://www.w3.org/TR/sparql12-protocol/
[SPARQL12-Query]
SPARQL 1.2 查询语言。Olaf Hartig;Andy Seaborne;Ruben Taelman;Gregory Williams;Thomas Pellissier Tanon。W3C。2026 年 6 月 24 日。 W3C 工作草案。URL:https://www.w3.org/TR/sparql12-query/
[SPARQL12-Update]
SPARQL 1.2 更新。Ruben Taelman; Andy Seaborne;Thomas Pellissier Tanon。W3C。2026 年 6 月 12 日。W3C 工作草案。URL:https://www.w3.org/TR/sparql12-update/
[TURTLE]
RDF 1.1 Turtle。Eric Prud'hommeaux;Gavin Carothers。W3C。2014 年 2 月 25 日。W3C 推荐标准。URL:https://www.w3.org/TR/turtle/
[UAX31]
Unicode 标识符和 语法。Mark Davis;Robin Leroy。Unicode Consortium。2025 年 8 月 20 日。Unicode 标准附录 #31。URL:https://www.unicode.org/reports/tr31/tr31-43.html
[UNICODE]
Unicode 标准。Unicode Consortium。URL:https://www.unicode.org/versions/latest/
[UTR36]
Unicode 安全 注意事项。Mark Davis;Michel Suignard。Unicode Consortium。2014 年 9 月 19 日。 Unicode 技术报告 #36。URL:https://www.unicode.org/reports/tr36/tr36-15.html
[vcard-rdf]
vCard 词汇表 - 用于描述人和 组织。Renato Iannella;James McKinney。W3C。2014 年 5 月 22 日。W3C 工作 组说明。URL:https://www.w3.org/TR/vcard-rdf/
[WEBARCH]
万维网架构,第 一卷。Ian Jacobs;Norman Walsh。W3C。2004 年 12 月 15 日。W3C 推荐标准。URL:https://www.w3.org/TR/webarch/
[XML-NAMES11]
XML 1.1 中的命名空间(第二 版)。Tim Bray;Dave Hollander;Andrew Layman;Richard Tobin 等。W3C。2006 年 8 月 16 日。 W3C 推荐标准。URL:https://www.w3.org/TR/xml-names11/
[XML11]
可扩展标记语言(XML)1.1(第二 版)。Tim Bray;Jean Paoli;Michael Sperberg-McQueen;Eve Maler;François Yergeau;John Cowan 等。W3C。2006 年 8 月 16 日。W3C 推荐标准。URL:https://www.w3.org/TR/xml11/
[XMLSCHEMA11-2]
W3C XML Schema 定义语言(XSD)1.1 第 2 部分:数据类型。David Peterson;Sandy Gao;Ashok Malhotra;Michael Sperberg-McQueen;Henry Thompson;Paul V. Biron 等。W3C。2012 年 4 月 5 日。W3C 推荐标准。URL: https://www.w3.org/TR/xmlschema11-2/
[XPATH-31]
XML 路径语言(XPath)3.1。Jonathan Robie;Michael Dyck;Josh Spiegel。W3C。2017 年 3 月 21 日。W3C 推荐标准。URL:https://www.w3.org/TR/xpath-31/
[XPATH-DATAMODEL-31]
XQuery 和 XPath 数据模型 3.1。Norman Walsh;John Snelson;Andrew Coleman。W3C。2017 年 3 月 21 日。W3C 推荐标准。URL:https://www.w3.org/TR/xpath-datamodel-31/
[XPATH-FUNCTIONS-31]
XPath 和 XQuery 函数与运算符 3.1。Michael Kay。W3C。2017 年 3 月 21 日。W3C 推荐标准。URL:https://www.w3.org/TR/xpath-functions-31/

F.2 资料性参考文献

[RDF12-TURTLE]
RDF 1.2 Turtle. Gregg Kellogg; Andy Seaborne; Dominik Tomaszuk. W3C. 2026 年 6 月 12 日. W3C 工作草案. URL: https://www.w3.org/TR/rdf12-turtle/
[SPARQL12-CONCEPTS]
SPARQL 1.2 Concepts. The W3C RDF & SPARQL Working Group. W3C. W3C 编辑草案. URL: https://w3c.github.io/sparql-concepts/spec/
[SPARQL12-ENTAILMENT]
SPARQL 1.2 Entailment Regimes. Peter Patel-Schneider. W3C. 2026 年 4 月 9 日. W3C 工作草案. URL: https://www.w3.org/TR/sparql12-entailment/
[SPARQL12-FEDERATED-QUERY]
SPARQL 1.2 Federated Query. Ruben Taelman; Gregory Williams. W3C. 2026 年 4 月 23 日. W3C 工作草案. URL: https://www.w3.org/TR/sparql12-federated-query/
[SPARQL12-GRAPH-STORE-PROTOCOL]
SPARQL 1.2 Graph Store Protocol. Andy Seaborne; Thomas Pellissier Tanon. W3C. 2024 年 12 月 19 日. W3C 工作草案. URL: https://www.w3.org/TR/sparql12-graph-store-protocol/
[SPARQL12-NEW]
SPARQL 1.2 新内容. The W3C RDF & SPARQL Working Group. W3C. W3C 编辑草案. URL: https://w3c.github.io/sparql-new/spec/
[SPARQL12-RESULTS-CSV-TSV]
SPARQL 1.2 Query Results CSV and TSV Formats. Ruben Taelman; Gregory Williams; Thomas Pellissier Tanon. W3C. 2026 年 3 月 28 日. W3C 工作草案. URL: https://www.w3.org/TR/sparql12-results-csv-tsv/
[SPARQL12-RESULTS-JSON]
SPARQL 1.2 Query Results JSON Format. Andy Seaborne; Ruben Taelman; Gregory Williams; Thomas Pellissier Tanon. W3C. 2026 年 3 月 28 日. W3C 工作草案. URL: https://www.w3.org/TR/sparql12-results-json/
[SPARQL12-RESULTS-XML]
SPARQL 1.2 Query Results XML Format. Ruben Taelman; Dominik Tomaszuk; Thomas Pellissier Tanon. W3C. 2024 年 12 月 27 日. W3C 工作草案. URL: https://www.w3.org/TR/sparql12-results-xml/
[SPARQL12-SERVICE-DESCRIPTION]
SPARQL 1.2 Service Description. Ruben Taelman; Gregory Williams. W3C. 2026 年 4 月 23 日. W3C 工作 草案. URL: https://www.w3.org/TR/sparql12-service-description/