# Role of foreign keys
Foreign keys play a crucial role for optimizing the saturated mapping assertions by doing some query containment checks.
Let us now consider the case where foreign keys are missing. Please download the following files: university-no-fk.ttl, university-no-fk.obda and university-no-fk.properties files.
Let us consider the case of foaf:Person
.
If you run the following SPARQL query in the absence of foreign keys:
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?p {
?p a foaf:Person .
}
you will obtain a SQL query similar to the following one (after some minor reformatting):
SELECT 1 AS "pQuestType", NULL AS "pLang",
('http://example.org/uni2/person/' || QVIEW1."lab_teacher") AS "p"
FROM "uni2"."course" QVIEW1
WHERE QVIEW1."lab_teacher" IS NOT NULL
UNION ALL
SELECT 1 AS "pQuestType", NULL AS "pLang",
('http://example.org/uni2/person/' || QVIEW1."lecturer") AS "p"
FROM "uni2"."course" QVIEW1
WHERE QVIEW1."lecturer" IS NOT NULL
UNION ALL
SELECT 1 AS "pQuestType", NULL AS "pLang",
('http://example.org/uni1/academic/' || QVIEW1."a_id") AS "p"
FROM "uni1"."teaching" QVIEW1
WHERE QVIEW1."a_id" IS NOT NULL
UNION ALL
SELECT 1 AS "pQuestType", NULL AS "pLang",
('http://example.org/uni2/person/' || QVIEW1."pid") AS "p"
FROM "uni2"."registration" QVIEW1
WHERE QVIEW1."pid" IS NOT NULL
UNION ALL
SELECT 1 AS "pQuestType", NULL AS "pLang",
('http://example.org/uni1/student/' || QVIEW1."s_id") AS "p"
FROM "uni1"."course-registration" QVIEW1
WHERE QVIEW1."s_id" IS NOT NULL
UNION ALL
SELECT 1 AS "pQuestType", NULL AS "pLang",
('http://example.org/uni1/student/' || QVIEW1."s_id") AS "p"
FROM "uni1"."student" QVIEW1
WHERE QVIEW1."s_id" IS NOT NULL
UNION ALL
SELECT 1 AS "pQuestType", NULL AS "pLang",
('http://example.org/uni1/academic/' || QVIEW1."a_id") AS "p"
FROM "uni1"."academic" QVIEW1
WHERE QVIEW1."a_id" IS NOT NULL
UNION ALL
SELECT 1 AS "pQuestType", NULL AS "pLang",
('http://example.org/uni2/person/' || QVIEW1."pid") AS "p"
FROM "uni2"."person" QVIEW1
WHERE QVIEW1."pid" IS NOT NULL
This SQL query is the union of eight sub-queries. Basically, it queries
the tables uni1.student
, uni1.academic
, uni2.person
as expected, but also
uni1.teaching
, uni1.course-registration
, uni2.course
and uni2.registration
.
Recall that the presence of the four latter tables is due to the fact that, according to the ontology, the respective domains of the properties :givesLecture
, :givesLab
and :attends
are subsumed by foaf:Person
.
With the setting of the first session which includes foreign keys, the generated SQL query contains only three unions:
SELECT 1 AS "pQuestType", NULL AS "pLang",
('http://example.org/uni1/student/' || QVIEW1."s_id") AS "p"
FROM "uni1"."student" QVIEW1
WHERE QVIEW1."s_id" IS NOT NULL
UNION ALL
SELECT 1 AS "pQuestType", NULL AS "pLang",
('http://example.org/uni1/academic/' || QVIEW1."a_id") AS "p"
FROM "uni1"."academic" QVIEW1
WHERE QVIEW1."a_id" IS NOT NULL
UNION ALL
SELECT 1 AS "pQuestType", NULL AS "pLang",
('http://example.org/uni2/person/' || QVIEW1."pid") AS "p"
FROM "uni2"."person" QVIEW1
WHERE QVIEW1."pid" IS NOT NULL
# Side note
If we now consider also the first and the last names of persons, foreign keys are not needed to optimize the query.
Try:
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?p ?firstName ?lastName {
?p a foaf:Person ;
foaf:firstName ?firstName ;
foaf:lastName ?lastName .
}
and observe that the query produces only three unions.
Why? Because the domain of foaf:firstName
and foaf:lastName
is foaf:Person
.
The SPARQL query can thus be safely rewritten as follow:
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?p ?firstName ?lastName {
?p foaf:firstName ?firstName ;
foaf:lastName ?lastName .
}