編輯後更新座標
我有一張
roads
桌子。道路線儲存在名為 的使用者定義類型列SHAPE
中。通常,空間實體只有
x
和y
維度。就我而言,我的道路有一個measure(m)
維度。這意味著我有x
、y
和m
尺寸。(M
值用於線性參考目的。)我有一個問題,我的 GIS 軟體在編輯和值時不會自動重置
m
線的值。這意味著在編輯行後,這些值會過期/不正確。x``y``m
我已經成功地弄清楚瞭如何產生新的
m
價值。誠然,查詢很長而且很複雜,但這不是目前的問題。我正在努力在這裡簡化它。select SDE.ST_GEOMFROMTEXT('LINESTRING M ( ' || listagg(X||' '||Y||' '||m,',') within group (order by VERTEX_INDEX) || ')', 300049) as WKT from (select ROAD_ID, VERTEX_INDEX, X, Y, ROUND(sum(m) over (partition by ROAD_ID order by VERTEX_INDEX),3) as m from (select ROAD_ID, VERTEX_INDEX, X, Y, case when VERTEX_INDEX = 1 then 0 else SQRT(power(abs((lag(X,1) over (partition by ROAD_ID order by VERTEX_INDEX))-X),2)+power(abs((lag(Y,1) over (partition by ROAD_ID order by VERTEX_INDEX))-Y),2)) end as m from ( select ROAD_ID, t.VERTEX_INDEX, SDE.ST_X(SDE.ST_POINTN(SHAPE, t.VERTEX_INDEX)) as X, SDE.ST_Y(SDE.ST_POINTN(SHAPE, t.VERTEX_INDEX)) as Y from USER1.ROADS cross join ( select level as VERTEX_INDEX from DUAL connect by level <= ( select max(SDE.ST_NUMPOINTS(SHAPE)) from USER1.ROADS ) ) t where t.VERTEX_INDEX <= SDE.ST_NUMPOINTS(SHAPE) and SDE.ST_GEOMETRYTYPE(SHAPE) <> 'ST_MULTILINESTRING' ) ) ) group by ROAD_ID Result: LINESTRING M ( 670495.21962780 4861662.29203628 0.00000000, 670644.70911652 4862034.07146977 400.70800781, 670579.99977367 4862214.15467259 592.06494141)
題:
編輯列後
SHAPE
(使用者更新x
andy
),我想採用新形狀,m
使用我的查詢重置值,然後SHAPE
使用重置值更新列m
。我認為解決方案將是一個相當簡單的觸發器。不幸的是,我對觸發器很陌生,並且在製作這個觸發器方面非常失敗。如何使用觸發器完成此操作?
更新:
我已經鼓起了一個基本的觸發器來開始:
create or replace trigger "RESET_M" before update of SHAPE on USER1.ROADS for each row declare begin :new.SHAPE := :new.SHAPE; end;
當然,這沒有幫助。它只是將 new
SHAPE
設置為相同的 newSHAPE
,這是沒有用的。我不知道如何使用我的查詢來做我想做的事。我想獲得編輯/更新的
x
和y
,計算新m
值,當然,將其送出到SHAPE
列。我想如果我使用函式,這會很容易。但是我的巨大查詢存在的根本原因是沒有一個函式可以做我需要做的事情。是的,Oracle Spatial確實有一個名為SDO_LRS.REDEFINE_GEOM_SEGMENT的函式,它可以滿足我的需求。但不幸的是,我沒有Oracle Spatial。
查看您的查詢,我們可以看到有很多細節無法在這裡討論。為了讓觸發器工作,這裡有一個小測試設置,可以幫助您執行後續步驟……
不太確定“LINESTRING M”值是否與原始 x/y 值儲存在同一個表中,這就是為什麼在編寫範例時考慮到 2 個表:(1)“shape_table”,包含 shape 類型的對象,以及(2) “m_values” 包含 road_id 和 “linestring m” 列(名稱縮短為 m)。DDL 如下。
create or replace type shape_t as object ( road_id number , vertex_index number , x number , prev_x number , y number , prev_y number , dist_to_prev number , member function getdistance return number ); / create table shape_table ( shp shape_t ) ; create table m_values ( road_id number, m varchar2(4000) );
插入一些測試數據後:
SQL> select * from shape_table; SHP(ROAD_ID, VERTEX_INDEX, X, PREV_X, Y, PREV_Y, DIST_TO_PREV) ----------------------------------------------------------------------------- SHAPE_T(100, 1, 0, 0, 5, 0, 0) SHAPE_T(100, 2, 10, 0, 10, 5, 11.18) SHAPE_T(100, 3, 30, 10, 0, 10, 22.36) SHAPE_T(100, 4, 50, 30, 10, 0, 22.36) SHAPE_T(100, 5, 60, 50, 10, 10, 10) SQL> select * from m_values; ROAD_ID M 100 LINESTRING M ( 0 5 0, 10 10 11.18, 30 0 33.54, 50 10 55.9, 60 10 65.9 )
現在,如果我們有重新計算“LINESTRING M”並將其用於更新的程序(由於各種原因,此處使用的 SELECT 看起來與您的問題中的不同*)
create or replace procedure refresh_m_value is m_roadid number := 0 ; m_linestring varchar2(4000) := '' ; begin -- generate the new M LINESTRING select road_id , 'LINESTRING M ( ' || listagg( x || ' ' || y || ' ' || dist_ , ', ' ) within group ( order by vi ) || ' )' linestring into m_roadid, m_linestring from ( select s.shp.road_id road_id , s.shp.vertex_index vi , round( s.shp.x, 2 ) x , round( s.shp.y, 2 ) y , sum ( s.shp.dist_to_prev ) over ( partition by s.shp.road_id order by s.shp.vertex_index ) dist_ from shape_table s ) roads_ group by road_id ; -- write the new M LINESTRING update m_values set m = m_linestring where road_id = m_roadid ; end refresh_m_value; /
在原始值被更新後,使用觸發器呼叫過程。添加用於調試/測試等的日誌表。
-- table for log messages generated by the trigger (see INSERTs in trigger code) create table trigger_log ( date_ date, message_ varchar2(128) ); create or replace trigger reset_m after update on shape_table declare error_code NUMBER; error_message VARCHAR2(128); begin refresh_m_value; insert into trigger_log (date_, message_) values (sysdate, '[trigger: reset_m] refresh_m_value executed ') ; exception when others then error_code := SQLCODE; error_message := SUBSTR(SQLERRM, 1 , 128); insert into trigger_log (date_, message_) values (sysdate, '[exception] ' || error_code || ' - ' || error_message); end; /
測試觸發器,檢查表(和日誌)。
update shape_table s set s.shp.x = 0, s.shp.y = 5 where s.shp.road_id = 100 and s.shp.vertex_index = 1 ; select * from shape_table; select * from trigger_log; select * from m_values;
- 有關(虛構的)TYPE shape_t 和填充“shapes_table”的更多詳細資訊,請參見此處。但是,使用 dbfiddle,由於 ORA-01031:權限不足,沒有成功創建 TYPE。