www.openlinksw.com
docs.openlinksw.com

Book Home

Contents
Preface

RDF Database and SPARQL

Overview
Data Representation
RDF and SPARQL API and SQL
SPARUL -- an Update Language For RDF Graphs
Introduction Manage RDF Storage Examples More Detailed Examples
RDF Insert Methods in Virtuoso
Virtuoso Sponger
Dereferencable IRIs and RDF Linked Data
RDF Views -- Mapping Relational Data to RDF
RDF Inference in Virtuoso
Using Full Text Search in SPARQL
Virtuoso SPARQL Query Service
Business Intelligence Extensions for SPARQL
Debugging SPARQL queries
Virtuoso RDF Performance Tuning
RDF Store Benchmarks
SPARQL Implementation Details
Native RDF Storage Providers

15.4. SPARUL -- an Update Language For RDF Graphs

15.4.1. Introduction

Starting from version 5.0, Virtuoso supports SPARQL/Update extension of SPARQL. This is sufficient for most of routine data manipulation operations. If SPARQL_UPDATE role is granted to SPARQL user then data manipulation statements may be executed via SPARQL web service endpoint as well as data querying.


15.4.2. Manage RDF Storage

Two functions allow the user to alter RDF storage by inserting or deleting all triples listed in some vector. Both functions receive an IRI of a graph that should be altered and a vector of triples that should be added or removed. The graph IRI can be either IRI ID or a string. The third optional argument of these functions control transactional behavior: the value of parameter is passed to log_enable function. The return values of functions are not defined and should not be used by applications.

create function DB.DBA.RDF_INSERT_TRIPLES (in graph_iri any, in triples any, in log_mode integer := null)
create function DB.DBA.RDF_DELETE_TRIPLES (in graph_iri any, in triples any, in log_mode integer := null)
       

Simple operations may be faster if written as low-level SQL code instead of using SPARUL. E.g, the use of SPARQL DELETE is redundant when the application should delete from RDF_QUAD by using simple filters like:

delete from DB.DBA.RDF_QUAD
where G = DB.DBA.RDF_MAKE_IID_OF_QNAME (
    'http://local.virt/DAV/sparql_demo/data/data-xml/source-simple2/source-data-01.rdf' );
       

On the other hand, simple filters does not work when search criteria refer to triples that are affected by the modification. Consider a function that deletes all triples whose subjects are nodes of type 'http://xmlns.com/foaf/0.1/Person'. Type information is stored in triples that will be deleted, so the simplest function is something like this:

create procedure DELETE_PERSONAL_DATA (in foaf_graph varchar)
{
  declare pdata_dict, pdata_array any;
-- Step 1: select everything that should be deleted
  pdata_dict := ((
      sparql construct { ?s ?p ?o }
      where { graph ?:foaf_graph {
              ?s ?p ?o . ?s rdf:type <http://xmlns.com/foaf/0.1/Person>
            } }
      ));
-- Step 2: delete all found triples
  pdata_array := dict_list_keys (pdata_dict, 1);
  RDF_DELETE_TRIPLES (foaf_graph, pdata_array);
};

DELETE_PERSONAL_DATA (
  'http://local.virt/DAV/sparql_demo/data/data-xml/source-simple2/source-data-01.rdf' );

Starting from Virtuoso 5.0, application may use SPARUL to do the same in a convenient way:

create procedure DELETE_PERSONAL_DATA (in foaf_graph varchar)
{
  sparql delete { ?s ?p ?o }
      where { graph ?:foaf_graph {
              ?s ?p ?o . ?s rdf:type <http://xmlns.com/foaf/0.1/Person>
            } }
};

15.4.3. Examples

The graph where changes take place may be specified by an option in front of query, instead of being specified in 'insert into graph' clause.

sparql define input:default-graph-uri <A-Named-Graph>
insert { <http://myopenlink.net/dataspace/Kingsley#this>
         <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>
         <http://rdfs.org/sioc/ns#User> };

The following two statements are equivalent but the latter may work faster, especially if there are many RDF views in the system or if some RDF views may contain triples for the graph in question. Note that neither of these two affect data that might come from RDF views.

sparql delete from graph <A-Named-Graph> { ?s ?p ?o } from <A-Named-Graph> where { ?s ?p ?o };
sparql clear graph <A-Named-Graph>;

Keywords 'insert in' and 'insert into' are interchangeable in Virtuoso for backward compatibility but SPARUL spec lists only 'insert into':

sparql insert into graph <A-Named-Graph> {  <http://myopenlink.net/dataspace/Kingsley#this>
                                            <http://rdfs.org/sioc/ns#id>
                                            <Kingsley> };
sparql insert into graph <A-Named-Graph> {  <http://myopenlink.net/dataspace/Caroline#this>
                                            <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>
                                            <http://rdfs.org/sioc/ns#User> };

It is possible to use various expressions to calculate fields of new triples. This is very convenient, even if not a part of the original spec.

sparql insert into graph <A-Named-Graph> { ?s <http://rdfs.org/sioc/ns#id> `iri (bif:concat (str (?o), "Idehen"))` }
where { ?s <http://rdfs.org/sioc/ns#id> ?o };

'Modify graph' may be used as a sort of 'update' operation.

sparql modify graph <A-Named-Graph> delete { ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?o } insert { ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type1> ?o } where { ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?o };
sparql delete from graph <A-Named-Graph> { <http://myopenlink.net/dataspace/Caroline#this> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type1> <http://rdfs.org/sioc/ns#User> };

The RDF information resource URI can be generated via a string expression.

sparql load bif:concat ("http://", bif:registry_get("URIQADefaultHost"), "/inputs/SparqlDawg/data-xml/Expr1/manifest.rdf")
   into graph <A-Named-Graph>;

Number of operations can be sent to a web service endpoint as a single statement and executed in sequence.

sparql
  insert in graph <A-Named-Graph> { <http://myopenlink.net/dataspace/Kingsley#this>
                                    <http://rdfs.org/sioc/ns#id>
                                    <Kingsley> }
  insert into graph <A-Named-Graph> { <http://myopenlink.net/dataspace/Caroline#this>
                                      <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>
                                      <http://rdfs.org/sioc/ns#User> }
  insert into graph <A-Named-Graph> { ?s <http://rdfs.org/sioc/ns#id> `iri (bif:concat (str (?o), "Idehen"))` }
              where { ?s <http://rdfs.org/sioc/ns#id> ?o };
  modify graph <A-Named-Graph> delete { ?s <p2> ?o } insert { ?s <p2new> ?o } where { ?s <p2> ?o }
  delete from graph <A-Named-Graph> { <http://myopenlink.net/dataspace/Caroline#this> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type1> <http://rdfs.org/sioc/ns#User> };
  load bif:concat ("http://", bif:registry_get("URIQADefaultHost"), "/inputs/SparqlDawg/data-xml/Expr1/manifest.rdf") into graph <A-Named-Graph>
;

In case of huge RDF data ( for ex. 600 million triples ) loaded in the Virtuoso sever in a single graph, the fastest operation to drop the graph is:

sparql clear graph <graph-iri>;

The operation may be accelerated using log_enable (0) or even log_enable (2), with log_enable(1) after the operation.


15.4.4. More Detailed Examples

Adding triples to graph

sparql
INSERT INTO GRAPH <http://BookStore.com>
{ <http://www.dajobe.org/foaf.rdf#i> <http://purl.org/dc/elements/1.1/title>  "SPARQL and RDF" .
  <http://www.dajobe.org/foaf.rdf#i> <http://purl.org/dc/elements/1.1/date> <1999-01-01T00:00:00>.
  <http://www.w3.org/People/Berners-Lee/card#i> <http://purl.org/dc/elements/1.1/title> "Design notes" .
  <http://www.w3.org/People/Berners-Lee/card#i> <http://purl.org/dc/elements/1.1/date> <2001-01-01T00:00:00>.
  <http://www.w3.org/People/Connolly/#me> <http://purl.org/dc/elements/1.1/title> "Fundamentals of Compiler Design" .
  <http://www.w3.org/People/Connolly/#me> <http://purl.org/dc/elements/1.1/date> <2002-01-01T00:00:00>. };

Adding triples to graph


    

A SPARQL/Update request that contains a triple to be deleted and a triple to be added (used here to correct a book title).

SPARQL
MODIFY GRAPH <http://BookStore.com>
DELETE
 { <http://www.w3.org/People/Connolly/#me>  <http://purl.org/dc/elements/1.1/title>  "Fundamentals of Compiler Design" }
INSERT
 { <http://www.w3.org/People/Connolly/#me>  <http://purl.org/dc/elements/1.1/title>  "Fundamentals" };
callret-0
VARCHAR
_______________________________________________________________________________

Modify <http://BookStore.com>, delete 1 and insert 1 triples -- done

1 Rows. -- 20 msec.

The example below has a request to delete all records of old books (with date before year 2000)

sparql
PREFIX dc:  <http://purl.org/dc/elements/1.1/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
DELETE FROM GRAPH <http://BookStore.com> { ?book ?p ?v }
WHERE
  { GRAPH  <http://BookStore.com>
   { ?book dc:date ?date
     FILTER ( xsd:dateTime(?date) < xsd:dateTime("2000-01-01T00:00:00")).
    ?book ?p ?v.
   }
  };
_______________________________________________________________________________

Delete from <http://BookStore.com>, 6 triples -- done

1 Rows. -- 10 msec.

This snippet copies records from one named graph to another named graph based on a pattern:

sparql
PREFIX dc:  <http://purl.org/dc/elements/1.1/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
INSERT INTO GRAPH <http://NewBookStore.com> { ?book ?p ?v }
WHERE
  { GRAPH  <http://BookStore.com>
   { ?book dc:date ?date
     FILTER ( xsd:dateTime(?date) > xsd:dateTime("2000-01-01T00:00:00")).
     ?book ?p ?v.
   }
  };
callret-0
VARCHAR
_______________________________________________________________________________

Insert into <http://NewBookStore.com>, 6 triples -- done

1 Rows. -- 30 msec.

An example to move records from one named graph to another named graph based on a pattern:

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

INSERT INTO GRAPH <http://NewBookStore.com>
 { ?book ?p ?v }
WHERE
  { GRAPH  <http://BookStore.com>
     { ?book dc:date ?date .
       FILTER ( xsd:dateTime(?date) > xsd:dateTime("2000-01-01T00:00:00")).
       ?book ?p ?v.
     }
  };
_______________________________________________________________________________

Insert into <http://NewBookStore.com>, 6 triples -- done

1 Rows. -- 10 msec.

sparql
PREFIX dc:  <http://purl.org/dc/elements/1.1/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
DELETE FROM GRAPH <http://BookStore.com>
 { ?book ?p ?v }
WHERE
  { GRAPH  <http://BookStore.com>
      { ?book dc:date ?date .
        FILTER ( xsd:dateTime(?date) > xsd:dateTime("2000-01-01T00:00:00")).
        ?book ?p ?v.
      }
  };
_______________________________________________________________________________

Delete from <http://BookStore.com>, 3 triples -- done

1 Rows. -- 10 msec.