Skip Headers
Oracle® Spatial and Graph RDF Semantic Graph Developer's Guide
12c Release 1 (12.1)

E17895-14
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
PDF · Mobi · ePub

10 RDF Views: Relational Data as RDF

This chapter explains how to create and use RDF views over relational data in Oracle Spatial and Graph RDF Semantic Graph. Relational data is viewed as virtual RDF triples using one of the two forms of RDB2RDF mapping described in W3C documents on Direct Mapping and R2RML mapping:

This chapter contains the following major sections:

10.1 Why Use RDF Views on Relational Data?

Using RDF views on relational data enables you to integrate data available from different sources. You can exploit the advantages of relational data without the need for physical storage of the RDF triples that correspond to the relational data. Before RDF views were included in RDF Semantic Graph in Oracle Database 12c Release 1 (12.1), you needed to write custom SQL queries or use non-standard mappings and physically store the generated RDF triples in an RDF model.

The simplest way to create a mapping of relational data to RDF data is by calling the SEM_APIS.CREATE_RDFVIEW_MODEL procedure to create an RDF view and supplying the list of tables or views whose content you would like to be viewed as RDF. This provides a direct mapping of those relational tables or views.

To get a more customized mapping, you can write an R2RML mapping document (in RDF using Turtle, for example) to specify the desired mapping, load the mapping document (after converting it to N-Triple format) into a staging table (for the table definition, see Section 1.7.1, "Bulk Loading Semantic Data Using a Staging Table"), and then call the SEM_APIS.CREATE_RDFVIEW_MODEL procedure to create an RDF view by supplying the name of the staging table.

10.2 API Support for RDF Views

Subprograms are included in the SEM_APIS package (documented in Chapter 11) for creating, dropping, and exporting (that is, materializing the content of) RDF views. An RDF view is created as an RDF model, but the RDF model physically contains only metadata. The actual data is still stored in the relational tables for which the RDF view has been created.

For the examples in the rest of this section, assume that the following relational tables exist in the invoker's schema:

CREATE TABLE dept (
  deptno NUMBER CONSTRAINT pk_DeptTab_deptno PRIMARY KEY,
  dname VARCHAR2(30),
  loc VARCHAR2(30)
);
 
CREATE TABLE emp ( 
  empno NUMBER PRIMARY KEY,
  ename VARCHAR2(30),
  job VARCHAR2(20),
  deptno NUMBER REFERENCES dept (deptno)
);

Note that if these tables are in a different schema (for example, SCOTT) than the invoker's, when specifying the names of these tables, you need to use schema-qualified table names: "SCOTT"."DEPT" and "SCOTT"."EMP".

10.2.1 Creating an RDF View with Direct Mapping

Example 10-1 creates an RDF view model using direct mapping of two tables, EMP and DEPT, with a base prefix of http://empdb/. The (virtual) RDF terms are generated according to A Direct Mapping of Relational Data to RDF, W3C Recommendation (http://www.w3.org/TR/rdb-direct-mapping/).

Example 10-1 Creating an RDF View with Direct Mapping

BEGIN
  sem_apis.create_rdfview_model(
    model_name => 'empdb_model',
    tables => SYS.ODCIVarchar2List('EMP', 'DEPT'),
    prefix => 'http://empdb/',
    options => 'KEY_BASED_REF_PROPERTY=T'
  );
END;
/

To see the properties that are generated, enter the following statement (which assumes that the objects are created in the schema of a user named TESTUSER):

SELECT DISTINCT p
  FROM TABLE(SEM_MATCH(
    '{?s ?p ?o}',
    SEM_Models('empdb_model'),
    NULL,
    NULL,
    NULL));
 
P                                                                               
--------------------------------------------------------------------------------
http://empdb/TESTUSER.EMP#DEPTNO                                                
http://empdb/TESTUSER.DEPT#LOC                                                  
http://empdb/TESTUSER.EMP#JOB                                                   
http://empdb/TESTUSER.DEPT#DEPTNO                                               
http://empdb/TESTUSER.EMP#ENAME                                                 
http://www.w3.org/1999/02/22-rdf-syntax-ns#type                                 
http://empdb/TESTUSER.DEPT#DNAME                                                
http://empdb/TESTUSER.EMP#EMPNO                                                 
http://empdb/TESTUSER.EMP#ref-DEPTNO                                            
 
9 rows selected.

Example 10-2 is essentially the same as Example 10-1, but it uses the CONFORMANCE=T option (see the options parameter description for SEM_APIS.CREATE_RDFVIEW_MODEL). Notice in the output that the schema name is not included in the list of properties; for example, the first output record in Example 10-2 is http://empdb/DEPT#LOC, whereas its counterpart generated by Example 10-1 is http://empdb/TESTUSER.DEPT#LOC.

Example 10-2 Using CONFORMANCE=T

BEGIN
  sem_apis.create_rdfview_model(
    model_name => 'empdb_model',
    tables => SYS.ODCIVarchar2List('EMP', 'DEPT'),
    prefix => 'http://empdb/',
    options => 'CONFORMANCE=T'
  );
END;
/

SELECT DISTINCT p
  FROM TABLE(SEM_MATCH(
    '{?s ?p ?o}',
    SEM_Models('empdb_model'),
    NULL,
    NULL,
    NULL));
 
P                                                                               
--------------------------------------------------------------------------------
http://empdb/DEPT#LOC                                                           
http://empdb/EMP#ref-DEPTNO                                                     
http://empdb/EMP#ENAME                                                          
http://empdb/DEPT#DEPTNO                                                        
http://empdb/EMP#JOB                                                            
http://empdb/EMP#EMPNO                                                          
http://www.w3.org/1999/02/22-rdf-syntax-ns#type                                 
http://empdb/DEPT#DNAME                                                         
http://empdb/EMP#DEPTNO                                                         
 
9 rows selected.

10.2.2 Creating an RDF View with an R2RML Mapping

If you wanted to create an RDF view using the two tables EMP and DEPT, but with your own customizations, you could create an R2RML mapping document specified using Turtle, such as the following:

@prefix rr: <http://www.w3.org/ns/r2rml#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix ex: <http://example.com/ns#>.
 
ex:TriplesMap_Dept
    rr:logicalTable [ rr:tableName "DEPT" ];
    rr:subjectMap [
        rr:template "http://data.example.com/department/{DEPTNO}";
        rr:class ex:Department;
    ];
    rr:predicateObjectMap [
        rr:predicate ex:deptNum;
        rr:objectMap [ rr:column "DEPTNO" ; rr:datatype xsd:integer ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:deptName;
        rr:objectMap [ rr:column "DNAME" ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:deptLocation;
        rr:objectMap [ rr:column "LOC" ];
    ].
 
ex:TriplesMap_Emp
    rr:logicalTable [ rr:tableName "EMP" ];
    rr:subjectMap [
        rr:template "http://data.example.com/employee/{EMPNO}";
        rr:class ex:Employee;
    ];
    rr:predicateObjectMap [
        rr:predicate ex:empNum;
        rr:objectMap [ rr:column "EMPNO" ; rr:datatype xsd:integer ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:empName;
        rr:objectMap [ rr:column "ENAME" ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:jobType;
        rr:objectMap [ rr:column "JOB" ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:worksForDeptNum;
        rr:objectMap [ rr:column "DEPTNO" ; rr:dataType xsd:integer ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:worksForDept;
        rr:objectMap [ 
          rr:parentTriplesMap ex:TriplesMap_Dept ; 
          rr:joinCondition [ rr:child "DEPTNO"; rr:parent "DEPTNO" ]]].

Then, load your R2RML mapping (converted into N-Triples format) into a staging table, such as SCOTT.R2RTAB, and grant the SELECT privilege for this table to MDSYS.

Next, call SEM_APIS.CREATE_RDFVIEW_MODEL, as in Example 10-3.

Example 10-3 Creating an RDF View with an R2RML Mapping

BEGIN
  sem_apis.create_rdfview_model(
    model_name => 'empdb_model',
    tables => NULL,
    r2rml_table_owner => 'SCOTT',
    r2rml_table_name => 'R2RTAB'
  );
END;
/

10.2.3 Dropping an RDF View

An RDF view can be dropped using the SEM_APIS.DROP_RDFVIEW_MODEL procedure, as shown in Example 10-4.

Example 10-4 Dropping an RDF View

BEGIN
  sem_apis.drop_rdfview_model(
    model_name => 'empdb_model'
  );
END;
/

10.2.4 Exporting Virtual Content of an RDF View into a Staging Table

The content of an RDF view is virtual; that is, the RDF triples corresponding to the underlying relational data, as mapped by direct mapping or R2RML mapping, are not materialized and stored anywhere. You may, however, want to materialize and store these virtual RDF triples in an RDF model for your testing purposes. The SEM_APIS.EXPORT_RDFVIEW_MODEL subprogram lets you store the RDF triples of an RDF view in a staging table. The staging table can then be used for loading into an RDF model.

Example 10-5 materializes (in N-Triples format) the content of RDF view empdb_model into the staging table SCOTT.RDFTAB.

Example 10-5 Exporting an RDF View

BEGIN
  sem_apis.export_rdfview_model(
    model_name => 'empdb_model',
    rdf_table_owner => 'SCOTT',
    rdf_table_name => 'RDFTAB'
  );
END;

10.3 Example: Using an RDF View with Direct Mapping

Example 10-6 shows a simple workflow using an RDF view with direct mapping. In it, you:

  1. Create two relational tables (EMP and DEPT).

  2. Insert data into the tables.

  3. Create an RDF view model (empdb_model) using direct mapping of the two tables.

  4. Query the RDF view using SPARQL in a SEM_MATCH-based SQL query.

Example 10-7 shows the output of the statements in Example 10-6.

Example 10-6 Using an RDF View with Direct Mapping

-- Use the following relational tables.
 
CREATE TABLE dept (
  deptno NUMBER CONSTRAINT pk_DeptTab_deptno PRIMARY KEY,
  dname VARCHAR2(30),
  loc VARCHAR2(30)
);
 
CREATE TABLE emp ( 
  empno NUMBER PRIMARY KEY,
  ename VARCHAR2(30),
  job VARCHAR2(20),
  deptno NUMBER REFERENCES dept (deptno)
);
 
-- Insert some data.
 
INSERT INTO dept (deptno, dname, loc)
  VALUES (1, 'Sales', 'Boston');
INSERT INTO dept (deptno, dname, loc)
  VALUES (2, 'Manufacturing', 'Chicago');
INSERT INTO dept (deptno, dname, loc)
  VALUES (3, 'Marketing', 'Boston');
 
INSERT INTO emp (empno, ename, job, deptno)
  VALUES (1, 'Alvarez', 'SalesRep', 1);
INSERT INTO emp (empno, ename, job, deptno)
  VALUES (2, 'Baxter', 'Supervisor', 2);
INSERT INTO emp (empno, ename, job, deptno)
  VALUES (3, 'Chen', 'Writer', 3);
INSERT INTO emp (empno, ename, job, deptno)
  VALUES (4, 'Davis', 'Technician', 2);
 
-- Create an RDF view model using direct mapping of two tables, EMP and DEPT, 
-- with a base prefix of http://empdb/.
-- Specify KEY_BASED_REF_PROPERTY=T for the options parameter.
 
BEGIN
  sem_apis.create_rdfview_model(
    model_name => 'empdb_model',
    tables => SYS.ODCIVarchar2List('EMP', 'DEPT'),
    prefix => 'http://empdb/',
    options => 'KEY_BASED_REF_PROPERTY=T'
  );
END;
/
 
-- Query an RDF view using SPARQL in a SEM_MATCH-based SQL query. 
-- The next statament is a query against an RDF view named empdb_model 
-- to find the employees who work for any department located in Boston.

SELECT emp
  FROM TABLE(SEM_MATCH(
  '{?emp emp:ref-DEPTNO ?dept . ?dept dept:LOC "Boston"}',
  SEM_Models('empdb_model'),
  NULL,
  SEM_ALIASES(
    SEM_ALIAS('dept','http://empdb/TESTUSER.DEPT#'),
    SEM_ALIAS('emp','http://empdb/TESTUSER.EMP#')
  ),
  null));

-- The preceding query is functionally comparable to this:
SELECT e.empno FROM emp e, dept d WHERE e.deptno = d.deptno AND d.loc = 'Boston';

Example 10-7 Output of Example 10-6, "Using an RDF View with Direct Mapping"

SQL> -- Use the following relational tables.
SQL> 
SQL> CREATE TABLE dept (
  2    deptno NUMBER CONSTRAINT pk_DeptTab_deptno PRIMARY KEY,
  3    dname VARCHAR2(30),
  4    loc VARCHAR2(30)
  5  );
 
Table created.
 
SQL> 
SQL> CREATE TABLE emp (
  2    empno NUMBER PRIMARY KEY,
  3    ename VARCHAR2(30),
  4    job VARCHAR2(20),
  5    deptno NUMBER REFERENCES dept (deptno)
  6  );
 
Table created.
 
SQL> 
SQL> -- Insert some data.
SQL> 
SQL> INSERT INTO dept (deptno, dname, loc)
  2    VALUES (1, 'Sales', 'Boston');
 
1 row created.
 
SQL> INSERT INTO dept (deptno, dname, loc)
  2    VALUES (2, 'Manufacturing', 'Chicago');
 
1 row created.
 
SQL> INSERT INTO dept (deptno, dname, loc)
  2    VALUES (3, 'Marketing', 'Boston');
 
1 row created.
 
SQL> 
SQL> INSERT INTO emp (empno, ename, job, deptno)
  2    VALUES (1, 'Alvarez', 'SalesRep', 1);
 
1 row created.
 
SQL> INSERT INTO emp (empno, ename, job, deptno)
  2    VALUES (2, 'Baxter', 'Supervisor', 2);
 
1 row created.
 
SQL> INSERT INTO emp (empno, ename, job, deptno)
  2    VALUES (3, 'Chen', 'Writer', 3);
 
1 row created.
 
SQL> INSERT INTO emp (empno, ename, job, deptno)
  2    VALUES (4, 'Davis', 'Technician', 2);
 
1 row created.
 
SQL> 
SQL> -- Create an RDF view model using direct mapping of two tables, EMP and DEPT,
SQL> -- with a base prefix of http://empdb/.
SQL> -- Specify KEY_BASED_REF_PROPERTY=T for the options parameter.
SQL> 
SQL> BEGIN
  2    sem_apis.create_rdfview_model(
  3      model_name => 'empdb_model',
  4      tables => SYS.ODCIVarchar2List('EMP', 'DEPT'),
  5      prefix => 'http://empdb/',
  6      options => 'KEY_BASED_REF_PROPERTY=T'
  7    );
  8  END;
  9  /
 
PL/SQL procedure successfully completed.
 
SQL> 
SQL> -- Query an RDF view using SPARQL in a SEM_MATCH-based SQL query.
SQL> -- The next statament is a query against an RDF view named empdb_model
SQL> -- to find the employees who work for any department located in Boston.
SQL> 
SQL> SELECT emp
  2    FROM TABLE(SEM_MATCH(
  3      '{?emp emp:ref-DEPTNO ?dept . ?dept dept:LOC "Boston"}',
  4      SEM_Models('empdb_model'),
  5      NULL,
  6      SEM_ALIASES(
  7        SEM_ALIAS('dept','http://empdb/TESTUSER.DEPT#'),
  8        SEM_ALIAS('emp','http://empdb/TESTUSER.EMP#')
  9      ),
 10      null));
 
EMP                                                                             
--------------------------------------------------------------------------------
http://empdb/TESTUSER.EMP/EMPNO=1                                               
http://empdb/TESTUSER.EMP/EMPNO=3                                               
 
SQL> 
SQL> -- The preceding query is functionally comparable to this:
SQL> SELECT e.empno FROM emp e, dept d WHERE e.deptno = d.deptno AND d.loc = 'Boston';
 
     EMPNO                                                                      
----------                                                                      
         1                                                                      
         3  

10.4 Combining Native RDF Data with Virtual RDB2RDF Data

You can combine native triple data with virtual RDB2RDF triple data in a single SEM_MATCH query by means of the SERVICE keyword. The SERVICE keyword is overloaded through the use of special SERVICE URLs that signify local (virtual) RDF data. The following prefixes are used to denote special SERVICE URLs:

  • Native models - oram: <http://xmlns.oracle.com/models/>

  • Native virtual models - oravm: <http://xmlns.oracle.com/virtual_models/>

  • RDB2RDF models - orardbm: <http://xmlns.oracle.com/rdb_models/>

Example 10-8 queries multiple data sets. In this query, the first triple pattern { ?x rdf:type :Person } will go against native model m1 as usual, but { ?x :name ?name } will go against the local native model m2, and { ?x :email ?email } will go against the local RDB2RDF model rdfview1.

Example 10-8 Querying Multiple Data Sets

select * from table (sem_match(
'SELECT ?x ?name ?email
 WHERE {
  ?x rdf:type :Person .
  OPTIONAL { SERVICE oram:m2 { ?x :name ?name } }
  OPTIONAL { SERVICE orardbm:rdfview1 { ?x :email ?email } }
}'
sem_models('m1'), null, null, null, null, ' '));

Overloaded SERVICE use is only allowed with a single model specified in the models argument of SEM_MATCH. Overloaded SERVICE queries do not allow multiple models or a rulebase as input. A virtual model that contains multiple models and/or entailments should be used instead for such combinations. In addition, the index_status argument for SEM_MATCH will only check the entailment contained in the virtual model passed as input in the models parameter. This means the status of entailments that are referenced in overloaded SERVICE calls will not be checked.

Example 10-9 queries two data sets: the empdb_model from Example 10-6, "Using an RDF View with Direct Mapping"and a native model named people.

Example 10-9 Querying Virtual RDB2RDF Data and Native RDF Data

-- Create native model people --
create table atab (gval varchar2(4000), tri sdo_rdf_triple_s);
 
execute sem_apis.create_sem_model('people','atab','tri');
 
create table stab(RDF$STC_GRAPH varchar2(4000), RDF$STC_sub varchar2(4000),
                  RDF$STC_pred varchar2(4000), RDF$STC_obj varchar2(4000));
grant select on stab to mdsys;
grant insert on atab to mdsys;
 
insert into stab values (null, '<http://empdb/TESTUSER.EMP/EMPNO=1>', '<http://people.org/age>', '"35"^^<http://www.w3.org/2001/XMLSchema#int>');
insert into stab values (null, '<http://empdb/TESTUSER.EMP/EMPNO=2>', '<http://people.org/age>', '"39"^^<http://www.w3.org/2001/XMLSchema#int>');
insert into stab values (null, '<http://empdb/TESTUSER.EMP/EMPNO=3>', '<http://people.org/age>', '"30"^^<http://www.w3.org/2001/XMLSchema#int>');
insert into stab values (null, '<http://empdb/TESTUSER.EMP/EMPNO=4>', '<http://people.org/age>', '"42"^^<http://www.w3.org/2001/XMLSchema#int>');
commit;
 
exec sem_apis.bulk_load_from_staging_table('people','testuser','stab');
 
-- Querying multiple datasets --
SELECT emp, age
  FROM TABLE(SEM_MATCH(
    'SELECT ?emp ?age WHERE{
       ?emp peop:age ?age
       SERVICE orardbm:empdb_model { ?emp emp:ref-DEPTNO ?dept . ?dept dept:LOC "Boston" }
    }',
    SEM_Models('people'),
    NULL,
    SEM_ALIASES(
          SEM_ALIAS('dept','http://empdb/TESTUSER.DEPT#'),
          SEM_ALIAS('emp','http://empdb/TESTUSER.EMP#'),
          SEM_ALIAS('peop','http://people.org/')
        ),
    NULL));