admin管理员组文章数量:1133719
I have a recursive procedure in a package in Oracle that traverses through a network. The recursive function runs down the network from the top and then returns values back up as the recursions close. On the way back up the network the function inserts the results of the step into an output table and will occasionally update records that should already exist (inserted in downstream recursions).
The logic for TRAVERSE_TRACE is roughly as follows:
- Find connected nodes downstream
- Call TRAVERSE_TRACE for each of the downstream nodes in the network
- Optionally update the output table entries below it
- Insert the current node into the output table
Once the entire recursive procedure has finished running I am able to see the inserted data in the output table but none of values set with the UPDATE statement.
The full procedure can be found here, but here is the section with the UPDATE and INSERT operations.
-- if the current feature is isolating, use the current downstream ISOs as the downstream ISOs for this area. If not then leave as null
IF v_IsolatingFeature = 1 THEN
v_downstreamIsolators := v_downstreamIsolatorsStaging;
v_downstreamIsolatorsStaging := G3E_FID;
UPDATE HEDLPROD.ISOLATION_AREA_ASSETS IA
SET IA.DOWNSTREAM_ISO_FIDS = to_char(v_downstreamIsolators)
WHERE IA.UPSTREAM_ISO_FID = to_number(G3E_FID);
COMMIT;
END IF;
-- Insert the current entry into the results table
Insert Into HEDLPROD.ISOLATION_AREA_ASSETS (FEEDERHEAD_FID, FEEDER, G3E_FID, G3E_FNO, UPSTREAM_ISO_FID, UPSTREAM_ASSET_FID, UPSTREAM_ISOLATORS, DOWNSTREAM_ISO_FIDS, DEPTH)
VALUES (v_feederHeadFid, FEEDER, G3E_FID, G3E_FNO, v_currentIsolatorFid, upstreamAssetFid, v_upstreamIsolatorFids,v_downstreamIsolators, v_depthCount);
COMMIT;
By adding DBMS logging I have identified that the where clause in the UPDATE statement is returning 0 records even though the insert statements for those entries have occurred earlier in the procedure.
The DBMS logging shows that the rows to be updated are being inserted before the update statement but that the select statement returns no records.
Rows Inserted into output table = 1. ID: 16312200, UPSTREAM_ID: 16309677
Rows Inserted into output table = 1. ID: 16309676, UPSTREAM_ID: 16309677
Number of rows where UPSTREAM_ID = 16309677 is: 0
Updating DOWNSTREAM_ISO_FIDS to 16312200 where UPSTREAM_ID = 16309677
Rows updated = 0. ID: 16309677
If I execute the update statement manually outside of the procedure then it works as expected.
Why are the inserted rows not showing up immediately? What can I do to force the rows to insert or to delay the update? Please help!
I have a recursive procedure in a package in Oracle that traverses through a network. The recursive function runs down the network from the top and then returns values back up as the recursions close. On the way back up the network the function inserts the results of the step into an output table and will occasionally update records that should already exist (inserted in downstream recursions).
The logic for TRAVERSE_TRACE is roughly as follows:
- Find connected nodes downstream
- Call TRAVERSE_TRACE for each of the downstream nodes in the network
- Optionally update the output table entries below it
- Insert the current node into the output table
Once the entire recursive procedure has finished running I am able to see the inserted data in the output table but none of values set with the UPDATE statement.
The full procedure can be found here, but here is the section with the UPDATE and INSERT operations.
-- if the current feature is isolating, use the current downstream ISOs as the downstream ISOs for this area. If not then leave as null
IF v_IsolatingFeature = 1 THEN
v_downstreamIsolators := v_downstreamIsolatorsStaging;
v_downstreamIsolatorsStaging := G3E_FID;
UPDATE HEDLPROD.ISOLATION_AREA_ASSETS IA
SET IA.DOWNSTREAM_ISO_FIDS = to_char(v_downstreamIsolators)
WHERE IA.UPSTREAM_ISO_FID = to_number(G3E_FID);
COMMIT;
END IF;
-- Insert the current entry into the results table
Insert Into HEDLPROD.ISOLATION_AREA_ASSETS (FEEDERHEAD_FID, FEEDER, G3E_FID, G3E_FNO, UPSTREAM_ISO_FID, UPSTREAM_ASSET_FID, UPSTREAM_ISOLATORS, DOWNSTREAM_ISO_FIDS, DEPTH)
VALUES (v_feederHeadFid, FEEDER, G3E_FID, G3E_FNO, v_currentIsolatorFid, upstreamAssetFid, v_upstreamIsolatorFids,v_downstreamIsolators, v_depthCount);
COMMIT;
By adding DBMS logging I have identified that the where clause in the UPDATE statement is returning 0 records even though the insert statements for those entries have occurred earlier in the procedure.
The DBMS logging shows that the rows to be updated are being inserted before the update statement but that the select statement returns no records.
Rows Inserted into output table = 1. ID: 16312200, UPSTREAM_ID: 16309677
Rows Inserted into output table = 1. ID: 16309676, UPSTREAM_ID: 16309677
Number of rows where UPSTREAM_ID = 16309677 is: 0
Updating DOWNSTREAM_ISO_FIDS to 16312200 where UPSTREAM_ID = 16309677
Rows updated = 0. ID: 16309677
If I execute the update statement manually outside of the procedure then it works as expected.
Why are the inserted rows not showing up immediately? What can I do to force the rows to insert or to delay the update? Please help!
Share Improve this question edited Jan 8 at 4:07 David Klein Ovink asked Jan 8 at 2:24 David Klein OvinkDavid Klein Ovink 31 silver badge3 bronze badges New contributor David Klein Ovink is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 4 |1 Answer
Reset to default 4This seems to be a scoping problem. According to your insert
Insert Into HEDLPROD.ISOLATION_AREA_ASSETS (FEEDERHEAD_FID, FEEDER, G3E_FID, G3E_FNO, UPSTREAM_ISO_FID, UPSTREAM_ASSET_FID, UPSTREAM_ISOLATORS, DOWNSTREAM_ISO_FIDS, DEPTH)
your ISOLATION_AREA_ASSETS
table has a column called G3E_FID
.
Your procedure definition also has a parameter called G3E_FID
:
PROCEDURE TRAVERSE_TRACE(
ITER_COUNT IN NUMBER DEFAULT 0,
FEEDER IN VARCHAR2,
G3E_FID IN NUMBER,
...
In your update statement you do:
WHERE IA.UPSTREAM_ISO_FID = to_number(G3E_FID);
and it appears that you're expecting that to match IA.UPSTREAM_ISO_FID
against the parameter G3E_FID
; but that's not what will happen. The name resolution rules say:
If a SQL statement references a name that belongs to both a column and either a local variable or formal parameter, then the column name takes precedence.
Caution: When a variable or parameter name is interpreted as a column name, data can be deleted, changed, or inserted unintentionally.
So you can read that as (without the superfluous function call):
WHERE IA.UPSTREAM_ISO_FID = IA.G3E_FID;
which it will only count or update when those two columns have the same value. Hence finding no matches, in the count and in the update. ; as shown in this simplified fiddle. (When you do it manually later you hard-code the numeric value, so there is no confusion.)
You could specify the parameter version using the procedure name, with:
WHERE IA.UPSTREAM_ISO_FID = TRAVERSE_TRACE.G3E_FID;
(fiddle)
But it's generally better to avoid parameter names that match schema identifiers completely, which is often done by prefixing them.
In this case you already have a local variable v_G3E_FID
you can use:
WHERE IA.UPSTREAM_ISO_FID = v_G3E_FID;
though it looks like you could rename for argument and all references to it to v_G3E_FID
and remove the local variable (fiddle).
I would recommend you rename/prefix all of the procedure arguments to avoid similar issues or just confusion and ambiguity for others trying to understand the code.
本文标签: sqlRows inserted in Oracle procedure not available until after the procedure completesStack Overflow
版权声明:本文标题:sql - Rows inserted in Oracle procedure not available until after the procedure completes - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736763039a1951660.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
where
clause you have:WHERE IA.UPSTREAM_ISO_FID = to_number(G3E_FID)
and think about what that's doing and when it's firing in your recursion logic. The code you've shown above does not help us because there is no obvious relationship between the value you originally inserted into the table and what you're looking for it to have in your later update where clause. It might make sense programmatically elsewhere, but that's hidden to us. – Paul W Commented Jan 8 at 3:25