How to write a correct SPARQL update statement with blank nodes?

49 Views Asked by At
@prefix  : <http://example.org/-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

:Person a rdf:Class ;
    :hasAttribute :name,:weight.

:Bob a :Person ;
    :hasAttribute [rdf:type :name;
            :hasValue 'Bob'],
      [rdf:type :height;
            :hasValue '1.67'^^xsd:decimal],
       [rdf:type :weight;
            :hasValue '70.2'^^xsd:decimal]. 

:John a :Person ;
    :hasAttribute [rdf:type :name;
            :hasValue 'John'],
      [rdf:type :height;
            :hasValue '1.71'^^xsd:decimal],
       [rdf:type :weight;
            :hasValue '70.2'^^xsd:decimal].

I want to update Bob's weight value in the above RDF file to 71.8, and I wrote the following SPARQL statement:

DELETE {
  ?person  :hasAttribute [ rdf:type  :weight;  :hasValue ?oldWeight ] .
}

INSERT {
  ?person  :hasAttribute [ rdf:type  :weight;  :hasValue "71.8"^^xsd:decimal ] .
}

WHERE {
  ?person rdf:type  :Person ;
           :hasAttribute [ rdf:type  :name;  :hasValue "Bob" ] .
  ?person  :hasAttribute [ rdf:type  :weight;  :hasValue ?oldWeight ] .
}

But I found it didn't work correctly, because the old weight value has not been deleted, but the new weight value has been added.

How should this be modified to correctly update Bob's weight value?

1

There are 1 best solutions below

0
Stefan - brox IT-Solutions On

Blank nodes are not allowed in DELETE, because

using a new blank node in a DELETE template would lead to nothing being deleted, as a new blank node cannot match anything in the Graph Store.

You can use SPARQL variables (e.g., ?name and ?weight) to refer to the existing blank nodes:

DELETE {

  ?person :hasAttribute ?weight .
  ?weight :hasValue ?oldWeightValue .

}

INSERT {

  ?person :hasAttribute [ 
    rdf:type :weight ;  
    :hasValue "71.8"^^xsd:decimal 
  ] .

}

WHERE {

  ?person a :Person ;
          :hasAttribute ?name , ?weight .

  ?name a :name ;
        :hasValue "Bob" .

  ?weight a :weight ;
        :hasValue ?oldWeightValue .

}

This should insert a new blank node for each solution found in the WHERE. So if there are two persons named Bob, it would add two blank nodes (each with a weight of 71.8).