Here is the answer from my side using different functions with a trigger.
Create Table.
create table linestrings (
id number primary key,
geom sdo_geometry
);
create table inspection (
id number primary key,
inspection_point sdo_geometry,
linestring_id number,
linestring_distance number,
projected_point sdo_geometry
);
Insert data into
insert into linestrings
values (
1,
sdo_geometry ('LINESTRING(0 5, 10 10, 30 0, 50 10, 60 10)')
);
commit;
Create geom index.
insert into user_sdo_geom_metadata
values (
'LINESTRINGS',
'GEOM',
sdo_dim_array (
sdo_dim_element('X',0,1000,0.05),
sdo_dim_element('Y',0,1000,0.05)
),
null
);
commit;
create index linestrings_sx on linestrings(geom) indextype is mdsys.spatial_index;
Create trigger.
create or replace trigger linestring_inspections
before inserting or updating inspection_point on the inspection
for each row
declare
linestring_id number;
linestring_distance number;
linestring_geom sdo_geometry;
geomb sdo_geometry;
projected_point sdo_geometry;
begin
-- Find nearest linestring
select id, geom
into linestring_id, linestring_geom
from linestrings
ORDER BY SDO_GEOM.SDO_DISTANCE(geom, :new.inspection_point, 1) ASC fetch first 1 rows only;
SDO_GEOM.SDO_CLOSEST_POINTS(linestring_geom, :new.inspection_point, 1.25, NULL, linestring_distance, projected_point, geomb);
-- Update inspection point
:new.linestring_id := linestring_id;
:new.linestring_distance := linestring_distance;
:new.projected_point := projected_point;
end;
Another trigger approach.
create or replace trigger linestring_inspections
before inserting or updating inspection_point on the inspection
for each row
declare
linestring_id number;
linestring_distance number;
linestring_geom sdo_geometry;
geoma sdo_geometry;
geom_distance number;
projected_point sdo_geometry;
begin
-- Find nearest linestring
select id, geom, sdo_nn_distance(1)
into linestring_id, linestring_geom, linestring_distance
from linestrings
where sdo_nn(geom, :new.inspection_point, 'sdo_num_res=1', 1) = 'TRUE';
SDO_GEOM.SDO_CLOSEST_POINTS(linestring_geom, :new.inspection_point, (linestring_distance*1.25/100), NULL, geom_distance, projected_point, geoma);
-- Update inspection point
:new.linestring_id := linestring_id;
:new.linestring_distance := linestring_distance;
:new.projected_point := projected_point;
end;
Insert data.
insert into inspection(id, inspection_point) values (101, sdo_geometry('POINT(20 1)'));
commit;
select id, SDO_UTIL.TO_WKTGEOMETRY(INSPECTION_POINT), SDO_UTIL.TO_WKTGEOMETRY(PROJECTED_POINT), LINESTRING_DISTANCE from inspection
Base answer copied from @Albert.