Oracle Databaseが持っている機能をAPEXから活用する方法を色々と確認してきましたが、Graphについてはまったく触ったことがなかったので、少し試してみました。
参照しているマニュアルはGraph Developer's Guide for RDF Graphです。
Autonomous Databaseでは制限事項として、マニュアルに以下の記載があります。
- SEM_MATCH (SPARQL in SQL API), SEM_APIS.UPDATE_MODEL and SEM_APIS.SPARQL_to_SQL are not supported
- Oracle Database 21c XEでグラフのネットワークとモデルを作成し、データを投入する。
- SEM_APIS.SPARQL_TO_SQLを実行し、SQLを生成する。
- Autonomous Databaseに全く同じグラフのネットワークとモデルを作成し、データを投入する。
- XE上で生成したSQLをAutonomous Database上で実行する。
begin
sem_apis.create_sem_network(
tablespace_name => 'APEXDEVのデフォルト表領域',
network_owner => 'APEXDEV',
network_name => 'NET1'
);
end;
/
SQL> select default_tablespace from user_users;
DEFAULT_TABLESPACE
------------------------------
APEX_2700775222008502
SQL> begin
sem_apis.create_sem_network(
tablespace_name => 'APEX_2700775222008502',
network_owner => 'APEXDEV',
network_name => 'NET1'
);
end;
/ 2 3 4 5 6 7 8
PL/SQL procedure successfully completed.
SQL>
begin
sem_apis.create_sem_model(
model_name => 'M1',
table_name => null,
column_name => null,
network_owner => 'APEXDEV',
network_name => 'NET1'
);
end;
/
SQL> begin
sem_apis.create_sem_model(
model_name => 'M1',
table_name => null,
column_name => null,
network_owner => 'APEXDEV',
network_name => 'NET1'
);
end;
/ 2 3 4 5 6 7 8 9 10
PL/SQL procedure successfully completed.
SQL>
SQL> set pages 1000 lines 180
SQL> set trims on trimo on
SQL> col owner format a8
SQL> col model_id format 99999999
SQL> col model_name format a10
SQL> col table_name format a10
SQL> col column_name format a12
SQL> col model_tablespace_name format a30
SQL> col model_type format a10
SQL> col i format a1
SQL> select * from net1#sem_model$;
OWNER MODEL_ID MODEL_NAME TABLE_NAME COLUMN_NAME MODEL_TABLESPACE_NAME MODEL_TYPE I
-------- --------- ---------- ---------- ------------ ------------------------------ ---------- -
APEXDEV 1 M1 APEX_2700775222008502 M F
SQL>
insert into net1#rdft_m1(triple) values(sdo_rdf_triple_s('M1','<urn:person1>','<urn:name>','"Peter"','APEXDEV','NET1'));
SQL> insert into net1#rdft_m1(triple) values(sdo_rdf_triple_s('M1','<urn:person1>','<urn:name>','"Peter"','APEXDEV','NET1'));
1 row created.
SQL> commit;
Commit complete.
SQL>
以上で準備は完了です。
select s$rdfterm, p$rdfterm, o$rdfterm
from table(sem_match(
query => 'SELECT ?s ?p ?o WHERE { ?s ?p ?o }'
, models => SEM_MODELS('M1')
, rulebases => null
, aliases => null
, filter => null
, index_status => null
, options =>' PLUS_RDFT=VC '
, graphs => null
, named_graphs => null
, network_owner => 'APEXDEV'
, network_name => 'NET1'
));
SQL> col s$rdfterm format a20
SQL> col p$rdfterm format a20
SQL> col o$rdfterm format a20
SQL> select s$rdfterm, p$rdfterm, o$rdfterm
from table(sem_match(
query => 'SELECT ?s ?p ?o WHERE { ?s ?p ?o }'
, models => SEM_MODELS('M1')
, rulebases => null
, aliases => null
, filter => null
, index_status => null
, options =>' PLUS_RDFT=VC '
, graphs => null
, named_graphs => null
, network_owner => 'APEXDEV'
, network_name => 'NET1'
)); 2 3 4 5 6 7 8 9 10 11 12 13 14
S$RDFTERM P$RDFTERM O$RDFTERM
-------------------- -------------------- --------------------
<urn:person1> <urn:name> "Peter"
SQL>
declare
sparql_stmt clob;
sql_stmt clob;
begin
sparql_stmt := 'SELECT ?s ?p ?o WHERE { ?s ?p ?o }';
sql_stmt :=
sem_apis.sparql_to_sql(
sparql_query => sparql_stmt
, models => sem_models('M1')
, rulebases => null
, aliases => null
, index_status => null
, options => ' PLUS_RDFT=VC '
, graphs => null
, named_graphs => null
, network_owner => 'APEXDEV'
, network_name => 'NET1'
);
dbms_output.put_line(sql_stmt);
end;
/
SQL> set serveroutput on
SQL> spool m1.sql
SQL> declare
sparql_stmt clob;
sql_stmt clob;
begin
sparql_stmt := 'SELECT ?s ?p ?o WHERE { ?s ?p ?o }';
sql_stmt :=
sem_apis.sparql_to_sql(
sparql_query => sparql_stmt
, models => sem_models('M1')
, rulebases => null
, aliases => null
, index_status => null
, options => ' PLUS_RDFT=VC '
, graphs => null
, named_graphs => null
, network_owner => 'APEXDEV'
, network_name => 'NET1'
);
dbms_output.put_line(sql_stmt);
end;
/
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 SELECT * FROM (
SELECT S,S$RDFVID,S$_PREFIX,S$_SUFFIX,S$RDFVTYP,S$RDFCLOB,S$RDFLTYP,S$RDFLANG,SEM_APIS.escape_rdf_term(S$RDFTERM, options=>' SPCLCH_ONLY=T
NETWORK_STORAGE_FORM=UNESC ') AS S$RDFTERM,P,P$RDFVID,P$_PREFIX,P$_SUFFIX,P$RDFVTYP,P$RDFCLOB,P$RDFLTYP,P$RDFLANG,SEM_APIS.escape_rdf_term(P$RDFTERM, options=>' SPCLCH_ONLY=T
NETWORK_STORAGE_FORM=UNESC ') AS P$RDFTERM,O,O$RDFVID,O$_PREFIX,O$_SUFFIX,O$RDFVTYP,O$RDFCLOB,O$RDFLTYP,O$RDFLANG,SEM_APIS.escape_rdf_term(O$RDFTERM, options=>' SPCLCH_ONLY=T
NETWORK_STORAGE_FORM=UNESC ') AS O$RDFTERM,SEM$ROWNUM AS SEM$ROWNUM
FROM (SELECT /*+ NO_MERGE(R) NO_SWAP_JOIN_INPUTS(R) LEADING(R V0 V1 V2) NO_SWAP_JOIN_INPUTS(V0)
NO_SWAP_JOIN_INPUTS(V1) NO_SWAP_JOIN_INPUTS(V2) */ V1.VNAME_PREFIX || V1.VNAME_SUFFIX AS S, V1.VALUE_ID AS S$RDFVID, V1.VNAME_PREFIX AS S$_PREFIX, V1.VNAME_SUFFIX AS S$_SUFFIX,
(CASE WHEN V1.VALUE_TYPE IS NULL THEN NULL WHEN V1.VALUE_TYPE IN ('UR','URI') THEN 'URI'
WHEN V1.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) AS S$RDFVTYP,
V1.LONG_VALUE AS S$RDFCLOB, V1.LITERAL_TYPE AS S$RDFLTYP, V1.LANGUAGE_TYPE AS S$RDFLANG,
CASE WHEN (CASE WHEN V1.VALUE_TYPE IS NULL THEN NULL WHEN V1.VALUE_TYPE IN ('UR','URI')
THEN 'URI'
WHEN V1.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) IS NULL
THEN NULL
WHEN (CASE WHEN V1.VALUE_TYPE IS NULL THEN NULL WHEN V1.VALUE_TYPE IN ('UR','URI')
THEN 'URI'
WHEN V1.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) IN ('UR','URI')
THEN '<' || V1.VNAME_PREFIX || V1.VNAME_SUFFIX || '>'
WHEN (CASE WHEN V1.VALUE_TYPE IS
NULL THEN NULL WHEN V1.VALUE_TYPE IN ('UR','URI') THEN 'URI'
WHEN V1.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) IN ('BL','BLN','BN')
THEN V1.VNAME_PREFIX ||
V1.VNAME_SUFFIX
ELSE
'"' || REPLACE(V1.VNAME_PREFIX || V1.VNAME_SUFFIX,chr(0)) || '"' || NVL2(V1.LANGUAGE_TYPE,'@' || V1.LANGUAGE_TYPE,'') || NVL2(V1.LITERAL_TYPE,'^^<' ||
V1.LITERAL_TYPE || '>', '')END AS S$RDFTERM,
V0.VNAME_PREFIX || V0.VNAME_SUFFIX AS P, V0.VALUE_ID AS P$RDFVID, V0.VNAME_PREFIX AS P$_PREFIX, V0.VNAME_SUFFIX AS P$_SUFFIX, (CASE
WHEN V0.VALUE_TYPE IS NULL THEN NULL WHEN V0.VALUE_TYPE IN ('UR','URI') THEN 'URI'
WHEN V0.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) AS P$RDFVTYP, V0.LONG_VALUE AS
P$RDFCLOB, V0.LITERAL_TYPE AS P$RDFLTYP, V0.LANGUAGE_TYPE AS P$RDFLANG,
CASE WHEN (CASE WHEN V0.VALUE_TYPE IS NULL THEN NULL WHEN V0.VALUE_TYPE IN ('UR','URI') THEN 'URI'
WHEN
V0.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) IS NULL
THEN NULL
WHEN (CASE WHEN V0.VALUE_TYPE IS NULL THEN NULL WHEN V0.VALUE_TYPE IN ('UR','URI') THEN 'URI'
WHEN
V0.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) IN ('UR','URI')
THEN '<' || V0.VNAME_PREFIX || V0.VNAME_SUFFIX || '>'
WHEN (CASE WHEN V0.VALUE_TYPE IS NULL THEN NULL
WHEN V0.VALUE_TYPE IN ('UR','URI') THEN 'URI'
WHEN V0.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) IN ('BL','BLN','BN')
THEN V0.VNAME_PREFIX ||
V0.VNAME_SUFFIX
ELSE
'"' || REPLACE(V0.VNAME_PREFIX || V0.VNAME_SUFFIX,chr(0)) || '"' || NVL2(V0.LANGUAGE_TYPE,'@' || V0.LANGUAGE_TYPE,'') || NVL2(V0.LITERAL_TYPE,'^^<' ||
V0.LITERAL_TYPE || '>', '')END AS P$RDFTERM,
V2.VNAME_PREFIX || V2.VNAME_SUFFIX AS O, V2.VALUE_ID AS O$RDFVID, V2.VNAME_PREFIX AS O$_PREFIX, V2.VNAME_SUFFIX AS O$_SUFFIX, (CASE
WHEN V2.VALUE_TYPE IS NULL THEN NULL WHEN V2.VALUE_TYPE IN ('UR','URI') THEN 'URI'
WHEN V2.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) AS O$RDFVTYP, V2.LONG_VALUE AS
O$RDFCLOB, V2.LITERAL_TYPE AS O$RDFLTYP, V2.LANGUAGE_TYPE AS O$RDFLANG,
CASE WHEN (CASE WHEN V2.VALUE_TYPE IS NULL THEN NULL WHEN V2.VALUE_TYPE IN ('UR','URI') THEN 'URI'
WHEN
V2.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) IS NULL
THEN NULL
WHEN (CASE WHEN V2.VALUE_TYPE IS NULL THEN NULL WHEN V2.VALUE_TYPE IN ('UR','URI') THEN 'URI'
WHEN
V2.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) IN ('UR','URI')
THEN '<' || V2.VNAME_PREFIX || V2.VNAME_SUFFIX || '>'
WHEN (CASE WHEN V2.VALUE_TYPE IS NULL THEN NULL
WHEN V2.VALUE_TYPE IN ('UR','URI') THEN 'URI'
WHEN V2.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
ELSE 'LIT'
END) IN ('BL','BLN','BN')
THEN V2.VNAME_PREFIX ||
V2.VNAME_SUFFIX
ELSE
'"' || REPLACE(V2.VNAME_PREFIX || V2.VNAME_SUFFIX,chr(0)) || '"' || NVL2(V2.LANGUAGE_TYPE,'@' || V2.LANGUAGE_TYPE,'') || NVL2(V2.LITERAL_TYPE,'^^<' ||
V2.LITERAL_TYPE || '>', '')END AS O$RDFTERM,
1 AS SEM$ROWNUM
FROM (SELECT T0.P_VALUE_ID AS P$RDFVID,
T0.START_NODE_ID AS S$RDFVID,
T0.CANON_END_NODE_ID AS
O$RDFVID,
T0.START_NODE_ID AS BGP$1
FROM (
SELECT * FROM "APEXDEV".NET1#RDFM_M1) T0
WHERE (1=1)) R, "APEXDEV".NET1#RDF_VALUE$ V0, "APEXDEV".NET1#RDF_VALUE$ V1,
"APEXDEV".NET1#RDF_VALUE$ V2
WHERE (1=1) AND (R.P$RDFVID = V0.VALUE_ID) AND (R.S$RDFVID = V1.VALUE_ID) AND (R.O$RDFVID = V2.VALUE_ID)) R
WHERE (1=1)
) WHERE (1=1)
PL/SQL procedure successfully completed.
SQL>
select
1 as triple_id,
'0123456789012345678901234567890123456789' as subject_name,
'0123456789012345678901234567890123456789' as property_name,
'0123456789012345678901234567890123456789' as object_value
from dual
insert into net1#rdft_m1(triple)
values(sdo_rdf_triple_s(
'M1',
:P3_SUBJECT_NAME,
:P3_PROPERTY_NAME,
'"' || :P3_OBJECT_VALUE || '"',
'APEXDEV',
'NET1'
));
これでモデルM1にデータを投入するフォームが出来上がりました。
begin
sem_apis.truncate_sem_model(
model_name => 'M1',
options => null,
network_owner => 'APEXDEV',
network_name => 'NET1'
);
end;
begin
sem_apis.drop_sem_model(
model_name => 'M1'
, options => null
, network_owner => 'APEXDEV'
, network_name => 'NET1'
);
end;
begin
sem_apis.drop_sem_network(
cascade => true
, options => null
, network_owner => 'APEXDEV'
, network_name => 'NET1'
);
end;