ORA-01779 on Join Update - oracle

I'm developing a web application on vb.net with Oracle as DB and I'm having some problems to update a table by using joins.
Since I'm kind of a newbie on Oracle, I can't make my query go on...i've been reading and I knew that oracle doesn't supports Joins on UPDATE, so i searched for alternatives and I finished on this:
UPDATE (SELECT pda.id_propuesta
FROM abd_prop_det_archivos pda
INNER JOIN abd_participantes_invitados pi
ON (pda.id_solicitud = pi.id_solicitud)
AND pi.id_solicitud = :id_solicitud
AND pi.rut = :rut)
SET id_propuesta = :id_propuesta
I'm using Oracle 11g.

It appears that you want a WHERE EXISTS clause
UPDATE abd_prop_det_archivos pda
SET ID_PROPUESTA = :ID_PROPUESTA
WHERE EXISTS( SELECT 1
FROM ABD_PARTICIPANTES_INVITADOS pi
WHERE pda.id_solicitud = pi.id_solicitud)
AND pi.id_solicitud = :id_solicitud
AND PI.RUT = :RUT )

Related

Oracle not using index, Entity Framework & Devart DotConnect for oracle

The table in question has ~30mio records. Using Entity Framework I write a LINQ Query like this:
dbContext.MyTable.FirstOrDefault(t => t.Col3 == "BQJCRHHNABKAKU-KBQPJGBKSA-N");
Devart DotConnect for Oracle generates this:
SELECT
Extent1.COL1,
Extent1.COL2,
Extent1.COL3
FROM MY_TABLE Extent1
WHERE (Extent1.COL3 = :p__linq__0) OR ((Extent1.COL3 IS NULL) AND (:p__linq__0 IS NULL))
FETCH FIRST 1 ROWS ONLY
The query takes about four minutes, obviously a full table scan.
However, handcrafting this SQL:
SELECT
Extent1.COL1,
Extent1.COL2,
Extent1.COL3
FROM MY_TABLE Extent1
WHERE Extent1.COL3 = :p__linq__0
FETCH FIRST 1 ROWS ONLY
returns the expected match in 200ms.
Question: Why is it so? I would expect the query optimizer to note that the right part is false if the parameter is not null, so why doesn't the first query hit the index?
Please set UseCSharpNullComparisonBehavior=false explicitly:
var config = Devart.Data.Oracle.Entity.Configuration.OracleEntityProviderConfig.Instance;
config.QueryOptions.UseCSharpNullComparisonBehavior = false;
If this doesn't help, send us a small test project with the corresponding DDL script so that we can investigate the issue.

Query failing on Oracle 12c and 18c when changing NLS_SORT to BINARY_CI

I have the following query which correctly returns records when I execute it via code or Oracle SQL Developer.
SELECT TABLE_T.COL_P,
1234 AS COL_C,
TABLE_T.COL_D,
SUM(SOME_COLUMN) Value
FROM TABLE_T
INNER JOIN TABLE_E E ON TABLE_T.COL_P = E.COL_P
AND TABLE_T.COL_C = E.COL_C
AND TABLE_T.COL_CC = E.COL_CC
AND TABLE_T.COL_CL = E.COL_CL
INNER JOIN TABLE_C C1 ON C1.COL_P = E.COL_P
AND C1.COL_C = E.COL_C
INNER JOIN TABLE_C C2 ON C2.COL_P = C1.COL_P
AND C2.COL_CX = C1.COL_CX
AND C2.COL_CY = C1.COL_CY
AND C2.COL_CZ = C1.COL_CZ
WHERE TABLE_T.COL_P = 'Some Text'
AND C2.COL_C = 1234
AND TABLE_T.COL_CL IN
(SELECT COL_CL
FROM TABLE_CL
WHERE COL_P = 'Some Text'
AND ((COL_CLTYPE = 'VALUE_A')
OR (COL_CLTYPE = 'VALUE_B')
OR (COL_CLTYPE = 'VALUE_C')
OR (COL_CLTYPE = 'VALUE_D')) )
GROUP BY TABLE_T.COL_P,
TABLE_T.COL_D
However, it fails to return records once I execute the following session commands:
ALTER SESSION SET NLS_COMP = LINGUISTIC;
ALTER SESSION SET NLS_SORT = BINARY_CI;
This problem only occurs when I'm running against an Oracle 12c or 18c database.
It works find with/without the session commands when running against an Oracle 12C R2 or 11g database.
I've already checked the Explain Plan for 12c/18c and 12cR2 and its creating the same plan.
I found out that by adding an ORDER BY clause to the query (ORDER BY TABLE_T.COL_D, it resolves the problem.
Any ideas on what might be causing this problem?
I know the ORDER BY solution works, but I'd like to know what the underlying cause is and if there's a better solution to it.

Using Merge in Oracle for updating a parent table using Joins

I have a SQL statement as below, I couldn't execute the statement in Oracle as it doesn't support Joins in Update. I have tried using updating using a temp table and completed the job, however, I would like to use the Merge statement and failed to write the code.
Let me know if there is a possibility in Oracle use joins in an update which doesn't add any performance overhead.
UPDATE A SET
YearStartPD = B.PERIOD_CODE,
YearEndPD = A.PERIOD_CODE,
PY_YearStartPD = C.PERIOD_CODE,
PY_YearEndPD = A.PY_WeekEndPD
FROM dbo.DIM_TIME A
INNER JOIN
(
select PERIOD_CODE,WEEK_PERIOD_CODE,YEAR_CODE from dbo.DIM_TIME
WHERE WEEK_PERIOD_CODE = '01'
) B ON B.Year_Code = A.Year_Code
LEFT JOIN
(
select PERIOD_CODE,WEEK_PERIOD_CODE,YEAR_CODE from dbo.DIM_TIME
WHERE WEEK_PERIOD_CODE = '01'
) C ON C.Year_Code = A.Year_Code - 1

How can I convert sql to linq

This is my SQL query
SELECT
sys.sysobjects.name Name,
sys.foreign_keys.*
FROM
sys.foreign_keys
inner join sys.sysobjects on
sys.foreign_keys.parent_object_id = sys.sysobjects.id
WHERE
referenced_object_id = OBJECT_ID(N'[dbo].[Country]')
I have installed Linqer to convert SQL to linq.
But I got an error:
SQL cannot be converted to LINQ: Table [foreign_keys] not found in the current Data Context.
I am a beginner in Linq. Can Anyone help me to convert SQL to Linq
The problem is that system views will not be picked up by Linqer. If you want to read these tables in your application, first create your own views on them, as was done here and write a query on these views.
CREATE VIEW SysObjectsView AS SELECT * FROM sys.sysobjects;
GO
CREATE VIEW SysForeignKeysView AS SELECT * FROM sys.foreign_keys;
GO
SELECT obj.name Name, fk.*
FROM SysForeignKeysView fk
INNER JOIN SysObjectsView obj ON fk.parent_object_id = obj.id
INNER JOIN SysObjectsView objfk ON fk.referenced_object_id = objfk.id
WHERE objfk.name = N'Country'
Linqer should be able to pick up these views.

Update value from a select statement

I'm using an Access over Oracle database system (Basically using Access for the forms and getting into the tables using ADO code) and am trying to update a field in the product table with the value of the same named field in a load table.
The code I am using is:
.CommandText = "UPDATE " & strSchema & ".TBL_CAPITAL_MGMT_PRODUCT a INNER JOIN " & strSchema & ".TBL_CAPITAL_MGMT_TEMP_LOAD b ON a.AR_ID = b.AR_ID SET a.TOT_RWA_AMT = b.TOT_RWA_AMT;"
Which returns an error about missing SET keyword.. So I changed it to:
.CommandText = "UPDATE (SELECT a.TOT_RWA_AMT, b.TOT_RWA_AMT As New_RWA_AMT FROM " & strSchema & ".TBL_CAPITAL_MGMT_TEMP_LOAD a INNER JOIN " & strSchema & ".TBL_CAPITAL_MGMT_PRODUCT b ON b.AR_ID = a.AR_ID Where a.New_Rec <> '-1' AND a.IP_ID Is Not Null) c SET c.New_RWA_AMT = c.TOT_RWA_AMT;"
Which returns an error about non key-preserved table. the b table has a pk of AR_ID but the a table has no primary key and it probably won't be getting one, I can't update the structure of any of the tables.
I tried using the /*+ BYPASS_UJVC */ which lets the code run, but doesn't actually seem to do anything.
Anyone got any ideas where I should go from here?
Thanks
Alex
Ignoring the irrelevant ADO code, the update you are trying to do is:
UPDATE TBL_CAPITAL_MGMT_PRODUCT a
INNER JOIN
SET a.TOT_RWA_AMT = b.TOT_RWA_AMT;
This isn't supported by Oracle (though maybe this undocumented BYPASS_UJVC hint is supposed to overcome that, but I wasn't aware of it till now).
Given that your inline view version fails due to lack of constraints you may have to fall back on the traditional Oracle approach using correlated subqueries:
UPDATE TBL_CAPITAL_MGMT_PRODUCT a
SET a.TOT_RWA_AMT = (SELECT b.TOT_RWA_AMT
FROM TBL_CAPITAL_MGMT_TEMP_LOAD b
WHERE a.AR_ID = b.AR_ID
)
WHERE EXISTS (SELECT NULL
FROM TBL_CAPITAL_MGMT_TEMP_LOAD b
WHERE a.AR_ID = b.AR_ID
);
The final WHERE clause is to prevent TOT_RWA_AMT being set to NULL on any "a" rows that don't have a matching "b" row. If you know that can never happen you can remove the WHERE clause.
If you're using Oracle 10g or higher, an alternative to Tony's solution would be to use a MERGE statement with only a MATCHED clause.
MERGE INTO TBL_CAPITAL_MGMT_PRODUCT a
USING TBL_CAPITAL_MGMT_TEMP_LOAD b
ON (a.AR_ID = b.AR_ID)
WHEN MATCHED THEN
UPDATE SET a.TOT_RWA_AMT = b.TOT_RWA_AMT;

Resources