1.15 Support for SPARQL Update Operations on an RDF Graph
Effective with Oracle Database Release 12.2, you can perform SPARQL Update operations on an RDF graph.
Note:
SPARQL update operations on an RDF graph is supported only if Oracle JVM is enabled on your Oracle Autonomous Database Serverless deployments. To enable Oracle JVM, see Use Oracle Java in Using Oracle Autonomous Database Serverless for more information.The W3C provides SPARQL 1.1 Update (https://www.w3.org/TR/2013/REC-sparql11-update-20130321/), an update language for RDF graphs. SPARQL 1.1 Update is supported in Oracle Database semantic technologies through the SEM_APIS.UPDATE_RDF_GRAPH procedure.
Before performing any SPARQL Update operations on an RDF graph, some prerequisites apply:
- The SEM_APIS.CREATE_SPARQL_UPDATE_TABLES procedure should be run in the schema of each user that will be using the SEM_APIS.UPDATE_RDF_GRAPH procedure.
- To update an RDF graph, the user should have
SELECT
,INSERT
,DELETE
,UPDATE
, andQUERY
privileges on the network and the target RDF graph. Note that these privileges are automatically present for the network owner. See Sharing Schema-Private RDF Networks to enable other users to update the RDF graph. - To run a LOAD operation, the user must have the CREATE ANY DIRECTORY and DROP
ANY DIRECTORY privileges, or the user must be granted READ privileges on an existing
directory object whose name is supplied in the
options
parameter.
The following examples show update operations being performed on an RDF graph. These examples assume a schema-private RDF network named NET1 owned by a database user named RDFUSER.
Example 1-117 INSERT DATA Operation
This example shows an INSERT DATA operation that inserts several triples in
the default electronics
graph.
-- Dataset before operation:
#Empty default graph
-- Update operation:
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
INSERT DATA {
:camera1 :name "Camera 1" .
:camera1 :price 120 .
:camera1 :cameraType :Camera .
:camera2 :name "Camera 2" .
:camera2 :price 150 .
:camera2 :cameraType :Camera .
} ',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
-- Dataset after operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera1 :name "Camera 1";
:price 120;
:cameraType :Camera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
Example 1-118 DELETE DATA Operation
This example shows a DELETE DATA operation that removes a single triple from
the default electronics
RDF graph.
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera1 :name "Camera 1";
:price 120;
:cameraType :Camera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
-- Update operation:
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
DELETE DATA { :camera1 :price 120 . } ',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
-- Dataset after operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera1 :name "Camera 1";
:cameraType :Camera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
Example 1-119 DELETE/INSERT Operation on Default Graph
This example performs a DELETE/INSERT operation. The
:
cameraType
of :camera1
is updated to
:
digitalCamera
.
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera1 :name "Camera 1";
:cameraType :Camera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
-- Update operation:
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
DELETE { :camera1 :cameraType ?type . }
INSERT { :camera1 :cameraType :digitalCamera . }
WHERE { :camera1 :cameraType ?type . }',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
-- Dataset after operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
Example 1-120 DELETE/INSERT Operation Involving Default Graph and Named Graph
Graphs can also be specified inside the DELETE and INSERT templates, as well as
inside the WHERE clause. This example moves all triples corresponding to digital cameras
from the default graph to the graph :digitalCameras
.
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Empty graph :digitalCameras
-- Update operation:
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
DELETE { ?s ?p ?o }
INSERT { graph :digitalCameras { ?s ?p ?o } }
WHERE { ?s :cameraType :digitalCamera .
?s ?p ?o }',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
-- Dataset after operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
Example 1-121 INSERT WHERE and DELETE WHERE Operations
One of either the DELETE template or the INSERT template can be omitted from a
DELETE/INSERT operation. In addition, the template following DELETE can be omitted as a
shortcut for using the WHERE pattern as the DELETE template. This example uses an INSERT
WHERE statement to insert the contents of the :digitalCameras
graph to the
:cameras
graph, and it uses a DELETE WHERE statement (with syntactic
shortcut) to delete all contents of the :cameras
graph.
-- INSERT WHERE
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
#Empty graph :cameras
-- Update operation:
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
INSERT { graph :cameras { ?s ?p ?o } }
WHERE { graph :digitalCameras { ?s ?p ?o } }',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
-- Dataset after operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
-- DELETE WHERE
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
-- Update operation:
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
DELETE WHERE { graph :cameras { ?s ?p ?o } }',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
-- Dataset after operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
#Empty graph :cameras
Example 1-122 COPY Operation
This example performs a COPY operation. All data from the default graph is
inserted into the graph :cameras
. Existing data from
:cameras
, if any, is removed before the insertion.
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
:camera3 :name "Camera 3" .
}
-- Update operation:
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
COPY DEFAULT TO GRAPH :cameras',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
-- Dataset after operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
}
Example 1-123 ADD Operation
This example adds all the triples in the graph :digitalCameras
to the graph :cameras
.
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
}
-- Update operation:
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
ADD GRAPH :digitalCameras TO GRAPH :cameras',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
-- Dataset after operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
}
Example 1-124 MOVE Operation
This example moves all the triples in the graph
:digitalCameras
to the graph :digCam
.
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
:camera4 :cameraType :digCamera .
}
-- Update operation:
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
MOVE GRAPH :digitalCameras TO GRAPH :digCam',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
-- Dataset after operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2" .
:camera2 :price 150 .
:camera2 :cameraType :Camera .
#Empty graph :digitalCameras
#Graph :cameras
GRAPH :cameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
Example 1-125 CLEAR Operation
This example performs a CLEAR operation, deleting all the triples in the default graph. Because empty graphs are not stored in the RDF graph, the CLEAR operation always succeeds and is equivalent to a DROP operation. (For the same reason, the CREATE operation has no effect on the RDF graph.)
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/>
#Default graph
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
#Empty graph :digitalCameras
#Graph :cameras
GRAPH :cameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
-- Update operation:
BEGIN
sem_apis.update_rdf_graph('electronics',
'CLEAR DEFAULT ',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
-- Dataset after operation:
@prefix : <http://www.example.org/electronics/>
#Empty Default graph
#Empty graph :digitalCameras
#Graph :cameras
GRAPH :cameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
Example 1-126 LOAD Operation
N-Triple, N-Quad, Turtle, and Trig files can be loaded from the local file
system using the LOAD operation. Note that the simpler N-Triple, and N-Quad formats can be
loaded faster than Turtle and Trig. An optional INTO clause can be used to load the file
into a specific named graph. To perform a LOAD operation, the user must either (1) have
CREATE ANY DIRECTORY and DROP ANY DIRECTORY privileges or (2) supply the name of an existing
directory object in the options
parameter of UPDATE_RDF_GRAPH. This example
loads the /home/oracle/example.nq N-Quad file into an RDF graph..
Note that the use of an INTO clause with an N-Quad or Trig file will override
any named graph information in the file. In this example, INTO GRAPH
:cameras
overrides :myGraph
for the first quad, so the subject,
property, object triple component of this quad is inserted into the
:cameras
graph instead.
-- Datafile: /home/oracle/example.nq
<http://www.example.org/electronics/camera3> <http://www.example.org/electronics/name> "Camera 3" <http://www.example.org/electronics/myGraph> .
<http://www.example.org/electronics/camera3> <http://www.example.org/electronics/price> "125"^^<http://www.w3.org/2001/XMLSchema#decimal> .
-- Dataset before operation:
#Graph :cameras
GRAPH :cameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
-- Update operation:
CREATE OR REPLACE DIRECTORY MY_DIR AS '/home/oracle';
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
LOAD <file:///example.nq> INTO GRAPH :cameras',
options=>'LOAD_DIR={MY_DIR}',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
END;
/
-- Dataset after operation:
@prefix : <http://www.example.org/electronics/>
#Graph :cameras
GRAPH :cameras {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
:camera2 :name "Camera 2";
:price 150;
:cameraType :Camera .
:camera3 :name "Camera 3";
:price 125.
}
#Graph :digCam
GRAPH :digCam {
:camera1 :name "Camera 1";
:cameraType :digitalCamera .
}
Several files under the same directory can be loaded in parallel with a single
LOAD operation. To specify extra N-Triple or N-Quad files to be loaded, you can use the
LOAD_OPTIONS hint. The degree of parallelism for the load can be specified with
PARALLEL(n)
in the options
string.. The
following example shows how to load the files /home/oracle/example1.nq
,
/home/oracle/example2.nq
, and /home/oracle/example3.nq
into an RDF graph. A degree of parallelism of 3 is used for this example.
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
LOAD <file:///example1.nq>',
options=> ' PARALLEL(3) LOAD_OPTIONS={ example2.nq example3.nq } LOAD_DIR={MY_DIR} ',
network_owner=>'RDFUSER', network_name=>'NET1' );
END;
/
Related subtopics:
- Tuning the Performance of SPARQL Update Operations
- Transaction Management with SPARQL Update Operations
- Support for Bulk Operations
- Setting UPDATE_RDF_GRAPH Options at the Session Level
- Load Operations: Special Considerations for SPARQL Update
- Long Literals: Special Considerations for SPARQL Update
- Blank Nodes: Special Considerations for SPARQL Update
Parent topic: RDF Graph Overview
1.15.1 Tuning the Performance of SPARQL Update Operations
In some cases it may be necessary to tune the performance of SPARQL Update operations. Because SPARQL Update operations involve executing one or more SPARQL queries based on the WHERE clause in the UPDATE statement, the Best Practices for Query Performance also apply to SPARQL Update operations. The following considerations also apply:
-
Delete operations require an appropriate index on the application table (associated with the
apply_model
parameter in SEM_APIS.UPDATE_RDF_GRAPH) for good performance. Assuming an application table named APP_TAB with the SDO_RDF_TRIPLE_S column named TRIPLE, an index similar to the following is recommended (this is the same index used by RDF Graph Support for Apache Jena):-- Application table index for -- (graph_id, subject_id, predicate_id, canonical_object_id) CREATE INDEX app_tab_idx ON app_tab app ( BITAND(app.triple.rdf_m_id,79228162514264337589248983040)/4294967296, app.triple.rdf_s_id, app.triple.rdf_p_id, app.triple.rdf_c_id) COMPRESS;
-
Performance-related SEM_MATCH options can be passed to the
match_options
parameter of SEM_APIS.UPDATE_RDF_GRAPH, and performance-related options such as PARALLEL and DYNAMIC_SAMPLING can be specified in theoptions
parameter of that procedure. The following example uses the options parameter to specify a degree of parallelism of 4 and an optimizer dynamic sampling level of 6 for the update. In addition, the example uses ALLOW_DUP=T as a match option when matching against the RDF graph collection VM1.BEGIN sem_apis.update_rdf_graph( 'electronics', 'PREFIX : <http://www.example.org/electronics/> INSERT { graph :digitalCameras { ?s ?p ?o } } WHERE { ?s :cameraType :digitalCamera . ?s ?p ?o }', match_models=>sem_models('VM1'), match_models=>sem_models('VM1'), match_options=>' ALLOW_DUP=T ', options=>' PARALLEL(4) DYNAMIC_SAMPLING(6) ', network_owner=>'RDFUSER', network_name=>'NET1'); END; /
-
Inline Query Optimizer Hints can be specified in the WHERE clause. The following example extends the preceding example by using the HINT0 hint in the WHERE clause and the FINAL_VALUE_NL hint in the
match_options
parameter.BEGIN sem_apis.update_rdf_graph( 'electronics', 'PREFIX : <http://www.example.org/electronics/> INSERT { graph :digitalCameras { ?s ?p ?o } } WHERE { # HINT0={ LEADING(t0 t1) USE_NL(t0 t1) ?s :cameraType :digitalCamera . ?s ?p ?o }', match_models=>sem_models('VM1'), match_options=>' ALLOW_DUP=T FINAL_VALUE_NL ', options=>' PARALLEL(4) DYNAMIC_SAMPLING(6) ', network_owner=>'RDFUSER', network_name=>'NET1'); END; /
Parent topic: Support for SPARQL Update Operations on an RDF Graph
1.15.2 Transaction Management with SPARQL Update Operations
You can exercise some control over the number of transactions used and whether they are automatically committed by a SEM_APIS.UPDATE_RDF_GRAPH operation.
By default, the SEM_APIS.UPDATE_RDF_GRAPH procedure executes in a single transaction that is either committed upon successful completion or rolled back if an error occurs. For example, the following call executes three update operations (separated by semicolons) in a single transaction:
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX elec: <http://www.example.org/electronics/>
PREFIX ecom: <http://www.example.org/ecommerce/>
# insert camera data
INSERT DATA {
elec:camera1 elec:name "Camera 1" .
elec:camera1 elec:price 120 .
elec:camera1 elec:cameraType elec:DigitalCamera .
elec:camera2 elec:name "Camera 2" .
elec:camera2 elec:price 150 .
elec:camera2 elec:cameraType elec:DigitalCamera . };
# insert ecom:price triples
INSERT { ?c ecom:price ?p }
WHERE { ?c elec:price ?p };
# delete elec:price triples
DELETE WHERE { ?c elec:price ?p }',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
PL/SQL procedure successfully completed.
By contrast, the following example uses three separate SEM_APIS.UPDATE_RDF_GRAPH calls to execute the same three update operations in three separate transactions:
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX elec: <http://www.example.org/electronics/>
PREFIX ecom: <http://www.example.org/ecommerce/>
# insert camera data
INSERT DATA {
elec:camera1 elec:name "Camera 1" .
elec:camera1 elec:price 120 .
elec:camera1 elec:cameraType elec:DigitalCamera .
elec:camera2 elec:name "Camera 2" .
elec:camera2 elec:price 150 .
elec:camera2 elec:cameraType elec:DigitalCamera . }',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
PL/SQL procedure successfully completed.
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX elec: <http://www.example.org/electronics/>
PREFIX ecom: <http://www.example.org/ecommerce/>
# insert ecom:price triples
INSERT { ?c ecom:price ?p }
WHERE { ?c elec:price ?p }',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
PL/SQL procedure successfully completed.
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX elec: <http://www.example.org/electronics/>
PREFIX ecom: <http://www.example.org/ecommerce/>
# insert elec:price triples
DELETE WHERE { ?c elec:price ?p }',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
PL/SQL procedure successfully completed.
The AUTOCOMMIT=F
option can be used to prevent separate transactions
for each SEM_APIS.UPDATE_RDF_GRAPH
call. With this option, transaction management is the responsibility of the caller. The
following example shows how to execute the update operations in the preceding example as a
single transaction instead of three separate ones.
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX elec: <http://www.example.org/electronics/>
PREFIX ecom: <http://www.example.org/ecommerce/>
# insert camera data
INSERT DATA {
elec:camera1 elec:name "Camera 1" .
elec:camera1 elec:price 120 .
elec:camera1 elec:cameraType elec:DigitalCamera .
elec:camera2 elec:name "Camera 2" .
elec:camera2 elec:price 150 .
elec:camera2 elec:cameraType elec:DigitalCamera . }',
options=>' AUTOCOMMIT=F ',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
PL/SQL procedure successfully completed.
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX elec: <http://www.example.org/electronics/>
PREFIX ecom: <http://www.example.org/ecommerce/>
# insert ecom:price triples
INSERT { ?c ecom:price ?p }
WHERE { ?c elec:price ?p }',
options=>' AUTOCOMMIT=F ',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
PL/SQL procedure successfully completed.
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX elec: <http://www.example.org/electronics/>
PREFIX ecom: <http://www.example.org/ecommerce/>
# insert elec:price triples
DELETE WHERE { ?c elec:price ?p }',
options=>' AUTOCOMMIT=F ',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
PL/SQL procedure successfully completed.
COMMIT;
Commit complete.
However, the following cannot be used with the AUTOCOMMIT=F
option:
-
Bulk operations (
FORCE_BULK=T
,DEL_AS_INS=T
) -
LOAD
operations -
Materialization of intermediate data (
STREAMING=F
)
1.15.2.1 Transaction Isolation Levels
Oracle Database supports three different transaction isolation levels: read committed, serializable, and read-only.
Read committed isolation level is the default. Queries in a transaction using this isolation level see only data that was committed before the query – not the transaction – began and any changes made by the transaction itself. This isolation level allows the highest degree of concurrency.
Serializable isolation level queries see only data that was committed before the transaction began and any changes made by the transaction itself.
Read-only isolation level behaves like serializable isolation level but data cannot be modified by the transaction.
SEM_APIS.UPDATE_RDF_GRAPH supports read committed and serializable transaction isolation levels, and read committed is the default. SPARQL UPDATE operations are processed in the following basic steps.
-
A query is executed to obtain a set of triples to be deleted.
-
A query is executed to obtain a set of triples to be inserted.
-
Triples obtained in Step 1 are deleted.
-
Triples obtained in Step 2 are inserted.
With the default read committed isolation level, the underlying triple data may be
modified by concurrent transactions, so each step may see different data. In addition,
changes made by concurrent transactions will be visible to subsequent update operations
within the same SEM_APIS.UPDATE_RDF_GRAPH call. Note that steps 1 and 2 happen as a single step when using materialization of
intermediate data (STREAMING=F
), so underlying triple data cannot be
modified between steps 1 and 2 with this option. See Support for Bulk Operations for
more information about materialization of intermediate data.
Serializable isolation level can be used by specifying the
SERIALIZABLE=T
option. In this case, each step will only see data
that was committed before the update RDF graph operation began, and multiple update
operations executed in a single SEM_APIS.UPDATE_RDF_GRAPH call will not see modifications made by concurrent update operations
in other transactions. However, ORA-08177 errors will be raised if a SEM_APIS.UPDATE_RDF_GRAPH execution tries to update triples that were modified by a concurrent
transaction. When using SERIALIZABLE=T
, the application should detect
and handle ORA-08177 errors (for example, retry the update command if it could not be
serialized on the first attempt).
The following cannot be used with the SERIALIZABLE=T
option:
-
Bulk operations (
FORCE_BULK=T
,DEL_AS_INS=T
) -
LOAD
operations -
Materialization of intermediate data (
STREAMING=F
)
Parent topic: Transaction Management with SPARQL Update Operations
1.15.3 Support for Bulk Operations
SEM_APIS.UPDATE_RDF_GRAPH supports bulk operations for efficient execution of large updates. The following
options are provided; however, when using any of these bulk operations, serializable
isolation (SERIALIZABLE=T
) and autocommit false
(AUTOCOMMMIT=F
) cannot be used.
- Materialization of Intermediate Data (STREAMING=F)
- Using SEM_APIS.BULK_LOAD_RDF_GRAPH
- Using Delete as Insert (DEL_AS_INS=T)
Parent topic: Support for SPARQL Update Operations on an RDF Graph
1.15.3.1 Materialization of Intermediate Data (STREAMING=F)
By default, SEM_APIS.UPDATE_RDF_GRAPH executes two queries for a basic DELETE INSERT SPARQL Update operation: one query to find triples to delete and one query to find triples to insert. For some update operations with WHERE clauses that are expensive to evaluate, executing two queries may not give the best performance. In these cases, executing a single query for the WHERE clause, materializing the results, and then using the materialized results to construct triples to delete and triples to insert may give better performance. This approach incurs overhead from a DDL operation, but overall performance is likely to be better for complex update statements.
The following example update using this option (STREAMING=F
). Note that STREAMING=F
is not allowed with serializable isolation (SERIALIZABLE=T
) or autocommit false (AUTOCOMMIT=F
).
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
DELETE { ?s ?p ?o }
INSERT { graph :digitalCameras { ?s ?p ?o } }
WHERE { ?s :cameraType :digitalCamera .
?s ?p ?o }',
options=>' STREAMING=F ',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
Parent topic: Support for Bulk Operations
1.15.3.2 Using SEM_APIS.BULK_LOAD_RDF_GRAPH
For updates that insert a large number of triples (such as tens of thousands), the
default approach of incremental DML on the application table may not give acceptable
performance. In such cases, the FORCE_BULK=T
option can be specified so that
SEM_APIS.BULK_LOAD_RDF_GRAPH
is used instead of incremental DML.
However, not all update operations can use this optimization. The
FORCE_BULK=T
option is only allowed for a SEM_APIS.UPDATE_RDF_GRAPH
call with either a single ADD operation or a single INSERT WHERE operation. The use of SEM_APIS.BULK_LOAD_RDF_GRAPH
forces a series of commits and autonomous transactions, so the AUTOCOMMIT=F
and SERIALIZABLE=T
options are not allowed with
FORCE_BULK=T
. In addition, bulk load cannot be used with
CLOB_UPDATE_SUPPORT=T
.
SEM_APIS.BULK_LOAD_RDF_GRAPH
allows various customizations through its flags
parameter. SEM_APIS.UPDATE_RDF_GRAPH
supports the BULK_OPTIONS={ OPTIONS_STRING }
flag so that
OPTIONS_STRING
can be passed into the flags
input of SEM_APIS.BULK_LOAD_RDF_GRAPH
to customize bulk load options. The following example shows a SEM_APIS.UPDATE_RDF_GRAPH
invocation using the FORCE_BULK=T
option and BULK_OPTIONS
flag.
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX elec: <http://www.example.org/electronics/>
PREFIX ecom: <http://www.example.org/ecommerce/>
INSERT { ?c ecom:price ?p }
WHERE { ?c elec:price ?p }',
options=>' FORCE_BULK=T BULK_OPTIONS={ parallel=4 parallel_create_index }',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
Parent topic: Support for Bulk Operations
1.15.3.3 Using Delete as Insert (DEL_AS_INS=T)
For updates that delete a large number of triples (such as tens of thousands), the default approach of incremental DML on the application table may not give acceptable performance. For such cases, the DEL_AS_INS=T
option can be specified. With this option, a large delete operation is implemented as INSERT, TRUNCATE, and EXCHANGE PARTITION operations.
The use of DEL_AS_INS=T
causes a series of commits and autonomous
transactions, so this option cannot be used with SERIALIZABLE=T
or
AUTOCOMMIT=F
. In addition, this option can only be used with SEM_APIS.UPDATE_RDF_GRAPH
calls that involve a single DELETE WHERE operation, a single DROP operation, or a single CLEAR
operation.
Delete as insert internally uses SEM_APIS.MERGE_RDF_GRAPHS
during intermediate operations. The string OPTIONS_STRING
from the
MM_OPTIONS={ OPTIONS_STRING }
flag can be specified to customize options
for merging. The following example shows a SEM_APIS.UPDATE_RDF_GRAPH
invocation using the DEL_AS_INS=T
option and MM_OPTIONS
flag.
BEGIN
sem_apis.update_rdf_graph('electronics',
'CLEAR NAMED',
options=>' DEL_AS_INS=T MM_OPTIONS={ dop=4 } ',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
Parent topic: Support for Bulk Operations
1.15.4 Setting UPDATE_RDF_GRAPH Options at the Session Level
Some settings that affect the SEM_APIS.UPDATE_RDF_GRAPH
procedure’s behavior can be modified at the session level through the use of the special
MDSYS.SDO_SEM_UPDATE_CTX.SET_PARAM procedure. The following options can be set to true or false
at the session level: autocommit
, streaming
,
strict_bnode
, and clob_support
.
The MDSYS.SDO_SEM_UPDATE_CTX contains the following subprograms to get and set SEM_APIS.UPDATE_RDF_GRAPH parameters at the session level:
SQL> describe mdsys.sdo_sem_update_ctx
FUNCTION GET_PARAM RETURNS VARCHAR2
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
NAME VARCHAR2 IN
PROCEDURE SET_PARAM
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
NAME VARCHAR2 IN
VALUE VARCHAR2 IN
The following example causes all subsequent calls to the SEM_APIS.UPDATE_RDF_GRAPH
procedure to use the AUTOCOMMIT=F
setting, until the end of the session or the
next call to SEM_APIS.UPDATE_RDF_GRAPH
that specifies a different autocommit
value.
begin
mdsys.sdo_sem_update_ctx.set_param('autocommit','false');
end;
/
Parent topic: Support for SPARQL Update Operations on an RDF Graph
1.15.5 Load Operations: Special Considerations for SPARQL Update
The format of the file to load affects the amount of parallelism that can be used during the load process. Load operations have two phases:
-
Loading from the file system to a staging table
-
Calling SEM_APIS.BULK_LOAD_RDF_GRAPH to load from a staging table into an RDF graph
All supported data formats can use parallel execution in phase 2, but only N-Triple and N-Quad formats can use parallel execution in phase 1. In addition, if a load operation is interrupted during phase 2 after the staging table has been fully populated, loading can be resumed with the RESUME_LOAD=T
keyword in the options
parameter.
Load operations for RDF documents that contain object values longer than
NETWORK_MAX_STRING_SIZE
bytes may require additional operations. Load
operations on Turtle and Trig documents will automatically load all triples/quads regardless of
object value size. However, load operations on N-Triple and N-Quad documents will only load
triples/quads with object values that are less than NETWORK_MAX_STRING_SIZE
bytes in length. For N-Triple and N-Quad data, a second load operation should be issued with the
LOAD_CLOB_ONLY=T
option to also load triples/quads with object values larger
than NETWORK_MAX_STRING_SIZE
bytes.
Loads from Unix named pipes are only supported for N-Triple and N-Quad formats. Turtle and Trig files should be uncompressed, physical files.
Unicode characters are handled differently depending on the format of the RDF file to load. Unicode characters in N-Triple and N-Quad files should be escaped as \u<HEX><HEX><HEX><HEX>
or \U<HEX><HEX><HEX><HEX><HEX><HEX><HEX><HEX>
using the hex value of the Unicode codepoint value. Turtle and Trig files do not require Unicode escaping and can be directly loaded with unescaped Unicode values.
Example 1-127 Short and Long Literal Load for N-Quad Data
BEGIN
-- short literal load
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
LOAD <file:///example1.nq>',
options=> ' LOAD_DIR={MY_DIR} ',
network_owner=>'RDFUSER', network_name=>'NET1');
-- long literal load
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
LOAD <file:///example1.nq>',
options=> ' LOAD_DIR={MY_DIR} LOAD_CLOB_ONLY=T ',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
Parent topic: Support for SPARQL Update Operations on an RDF Graph
1.15.6 Long Literals: Special Considerations for SPARQL Update
By default, SPARQL Update operations do not manipulate values longer than
NETWORK_MAX_STRING_SIZE
bytes. To enable long literals support,
specify CLOB_UPDATE_SUPPORT=T
in the options parameter with the SEM_APIS.UPDATE_RDF_GRAPH procedure.
Bulk load does not work for long literals; the FORCE_BULK=T
option is ignored when used with the CLOB_UPDATE_SUPPORT=T
option.
Parent topic: Support for SPARQL Update Operations on an RDF Graph
1.15.7 Blank Nodes: Special Considerations for SPARQL Update
Some update operations only affect the graph of a set of RDF triples. Specifically,
these operations are ADD, COPY and MOVE. For example, the MOVE operation example in Support for SPARQL Update Operations on an RDF Graph can be performed only updating triples having
:digitalCameras
as the graph. However, the performance of such operations
can be improved by using ID-only operations over the RDF graph. To run a large ADD, COPY, or
MOVE operation as an ID-only operation, you can specify the STRICT_BNODE=F
hint in the options
parameter for the SEM_APIS.UPDATE_RDF_GRAPH
procedure.
ID-only operations may lead to incorrect blank nodes, however, because no two graphs should share the same blank node. RDF graph uses a blank node prefixing scheme based on the model (RDF graph) and named graph combination that contains a blank node. These prefixes ensure that blank node identifiers are unique across models (RDF graphs) and named graphs. An ID-only approach for ADD, COPY, and UPDATE operations does not update blank node prefixes.
Example 1-128 ID-Only Update Causing Incorrect Blank Node Values
The update in the following example leads to the same blank node subject for both triples in graphs :cameras
and :cameras2
. This can be verified running the provided SEM_MATCH query.
BEGIN
sem_apis.update_rdf_graph('electronics',
'PREFIX : <http://www.example.org/electronics/>
INSERT DATA {
GRAPH :cameras { :camera2 :owner _:bn1 .
_:bn1 :name "Axel" }
};
COPY :cameras TO :cameras2',
options=>' STRICT_BNODE=F ',
network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
SELECT count(s)
FROM TABLE( SEM_MATCH('
PREFIX : <http://www.example.org/electronics/>
SELECT *
WHERE { { graph :cameras {?s :name "Axel" } }
{ graph :cameras2 {?s :name "Axel" } } }
', sem_models('electronics'),null,null,null,null,' STRICT_DEFAULT=T ',
null, null, 'RDFUSER', 'NET1'));
To avoid such errors, you should specify the STRICT_BNODE=F
hint in
the options
parameter for the SEM_APIS.UPDATE_RDF_GRAPH procedure only when you are sure that blank nodes are not involved in the ADD, COPY, or
MOVE update operation.
However, ADD, COPY, and MOVE operations on large graphs with the
STRICT_BNODE=F
option may run significantly faster than they would run
using the default method. If you need to run a series of ID-only updates, another option is
to use the STRICT_BNODE=F
option, and then execute the SEM_APIS.CLEANUP_BNODES procedure at the end. This approach resets the prefix of all blank
nodes in a given RDF graph, which effectively corrects ("cleans up") all erroneous blank
node labels.
Note that this two-step strategy should not be used with a small number of ADD, COPY, or MOVE operations. Performing a few operations using the default approach will execute faster than running a few ID-only operations and then executing the SEM_APIS.CLEANUP_BNODES procedure.
The following example corrects blank nodes in the RDF graph named
electronics
.
EXECUTE sem_apis.cleanup_bnodes('electronics');
Parent topic: Support for SPARQL Update Operations on an RDF Graph