update on select ORA-01732 - oracle

I get on oracle-server ORA-01732.
There are any other issues with this ORA, but it does not help me on my situation.
I select typicaly some data from two tables and i group these something like this:
SELECT SUM (LG_ALL.HOURS) AS hour_sum,
TO_CHAR (LG_ALL.WORK_DATE, 'YYYY.MM') AS singel_month,
LG_ALL.EXPORTED
FROM USER usr,
USER_ALLWC LG_ALL,
WHERE usr.user_id = LG_ALL.user_id
AND LG_ALL.EXPORTED = 'N'
GROUP BY
TO_CHAR (LG_ALL.WORK_DATE, 'YYYY.MM'),
LG_ALL.EXPORTED
ORDER BY usr.LOGNAME DESC
At next step, I have to set on table USER_ALLWC:
LG_ALL.EXPORTED = 'Y'
Because of this, i wrap this into update-statement like
updates-based-on-queries => Inline View Method:
UPDATE ( SELECT SUM (LG_ALL.HOURS) AS hour_sum,
TO_CHAR (LG_ALL.WORK_DATE, 'YYYY.MM') AS singel_month,
LG_ALL.EXPORTED
FROM USER usr,
USER_ALLWC LG_ALL,
WHERE usr.user_id = LG_ALL.user_id
AND LG_ALL.EXPORTED = 'N'
GROUP BY
TO_CHAR (LG_ALL.WORK_DATE, 'YYYY.MM'),
LG_ALL.EXPORTED
ORDER BY usr.LOGNAME DESC ) allg
SET allg.EXPORTED = 'Y';
Sadly I get ORA-01732.
Can anyone explain, when I can update on select-statement and how can I fix it?

From Oracle SQL Language Reference:
The view must not contain any of the following constructs:
A set operator
A DISTINCT operator
An aggregate or analytic function
...
Try simplifying it - the sum, group by etc. add no value anyway:
UPDATE ( SELECT LG_ALL.EXPORTED
FROM USER usr,
USER_ALLWC LG_ALL,
WHERE usr.user_id = LG_ALL.user_id
AND LG_ALL.EXPORTED = 'N'
) allg
SET allg.EXPORTED = 'Y';
As long as there is a foreign key from USER_ALLWC to USER this should work.
In fact, assuming there is such a foreign key the whole statement is equivalent to:
UPDATE USER_ALLWC
SET EXPORTED = 'Y'
WHERE EXPORTED = 'N';

Related

Iterate a select query for a set of varchar2 in oracle

I have a below select query
select * from BUSINESS_T
where store_code = '075'
and item_no in
(
select item_no from BUSINESS_T a
where store_code = '075'
and exists
(
select * from BUSINESS_T
where store_code = a.store_code
and item_no = a.item_no
and
(
VALID_FROM_DTIME between a.VALID_FROM_DTIME and a.VALID_TO_DTIME
or VALID_TO_DTIME between a.VALID_FROM_DTIME and a.VALID_TO_DTIME
or (VALID_FROM_DTIME > a.VALID_FROM_DTIME and a.VALID_TO_DTIME is null)
or (VALID_FROM_DTIME < a.VALID_FROM_DTIME and VALID_TO_DTIME is null)
)
and del_dtime is null
and not
(
a.rowid = rowid
)
)
)
order by item_no, VALID_FROM_DTIME
Need to run it for a array of store numbers {'071','072','073','074','075','076'}
This array should defined inside the query itself.
Nearly 400+ fixed store numbers are there. The above query has to be run for each store, at a time for one store , To find the overlapping in that particular store
If i run by passing the collection of store numbers, there is a chance items are common in many stores that will cause a problem.
You can still use in if you modify the first subquery to get return the store/item pairs, which handles the common items:
select * from BUSINESS_T
where (store_code, item_no) in
(
select store_code, item_no from BUSINESS_T a
where store_code in ('071','072','073','074','075','076')
...
Or with a collection:
select * from BUSINESS_T
where (store_code, item_no) in
(
select store_code, item_no from BUSINESS_T a
where store_code member of sys.dbms_debug_vc2coll('071','072','073','074','075','076')
...
db<>fiddle with very simple demo of the idea.
Use in:
select *
from business_t
where
class_unit_code in ('071', '072', '073', '074', '075', '076')
and b_type = 'CASH_AND_CARRY'
and delete_date is null
For this specific sequence of string values, we might try to shorten the predicate using a regex (although this is probably less efficient):
regexp_like(class_unit_code, '^07[1-6]$')
Or if the string always contains numeric values, we can convert and use a range comparison (which also is not as efficient as the first option - in that case, the column should have been created with a numeric datatype to start with):
to_number(class_unit_code) between 71 and 76

SELECT within UPDATE gives an error

I am getting SQL Error: ORA-01779: cannot modify a column which maps to a non key-preserved table error on this statement:
UPDATE
(
SELECT CELLS.NUM, UND.CLIENT_PARAMS
FROM CELLS
LEFT OUTER JOIN UND
ON CELLS.UND_ID = UND.ID
WHERE CELLS.SASE = 1
) t
SET t.CLIENT_PARAMS = 'test';
I would like to update CLIENT_PARAMS field for all rows, which select returns.
The most straightforward (though possibly not the most efficient) way to update rows in one table which correspond directly to rows in another table via an identity column would be to use WHERE table1.column IN (SELECT id FROM table2 WHERE ...).
In this case:
UPDATE UND
SET client_params = 'test'
WHERE id IN
(SELECT und_id
FROM CELLS
WHERE SASE=1)
Try this
UPDATE und u
SET client_params = 'test'
WHERE EXISTS
(SELECT 1
FROM cells c
WHERE C.SASE = 1
AND c.und_id = u.id)

Using IF statements in Oracle when trying to return data

How do I return data out of IF statements? I have a IF statement which is meant to return a different result dependent of the result of that statement.
IF :Value = 1 THEN
SELECT Name FROM TABLE_A
ELSEIF :Value = 2 THEN
SELECT Name FROM TABLE_B
ELSEIF :Value = 3 THEN
SELECT Name FROM TABLE_C
but this doesn't work. It expects an INTO statement in those selects. I suspect this is because Oracle can't return out of a block?
Is there a quicker way to return those select statements without creating table variables to store the data or messing around with functions?
You can do this by plain SQL:
SELECT
':Value' user_input,
CASE
WHEN ':Value' IN('a1','a2','a3')
THEN (select name from table_a)
WHEN ':Value' = 'i'
THEN (select name from table_b)
END AS output
FROM
dual
(good info about case)
If you want more than one result in your cases, then you may opt to an intelligent UNION:
SELECT t1_Col_1, t1_Col_2,'&VALUE' from TABLE_1
WHERE '&VALUE' = '1'
UNION ALL
SELECT t2_Col_1, t2_Col_2,'&VALUE' from TABLE_2
WHERE '&VALUE' = '2'
In this solution, types and number of tx_Coln must be the same.

Oracle-update multiple row value where the the id column equals specific values

I am new in oracle and I want to update multiple row value where the column id = 1 , 2.
I tried this :
update Tester
set employee_phone_number = ( 0789456123,0789456321)
where employee_id in (1,2);
but it gives me "missing right parenthesis"
any help please and thanks in advance.
Another approach:
merge into
tester
using (
select 1 id,'0123456785' employee_phone_number from dual union all
select 2 id,'0123456786' employee_phone_number from dual) new_values
on (
tester.id = new_values.id)
when matched then update
set employee_phone_number = new_values.employee_phone_number;
More words, but allows the values to be specified in only one place and extends to allow inserts where the id does not already exist.
http://sqlfiddle.com/#!4/8fc86/3
Try this instead:
update Tester
set employee_phone_number = CASE WHEN employee_id = 1 THEN 0789456123
WHEN employee_id = 2 THEN 0789456321
END
where employee_id in (1,2);

Need a fix for merge update query (Simple but still confusing)

MERGE INTO table_1 a
USING
(SELECT * from table_2) b ON ( a.row_id = b.row_id and a.in_correct IS NULL)
WHEN MATCHED THEN UPDATE SET a.in_correct = 'Y';
In the above query ORA-38104:Column referenced in ON clause cannot be updated.
I have been sitting for hours to resolve this.
I have identified that the problem is the field in_correct.
This field "in_correct" cannot be put in both ON clause and also after SET. But in order satisfy my criteria,I have no option.
Please help me out
MERGE INTO table_1 a USING
(SELECT * from table_2) b
ON ( a.row_id = b.row_id)
WHEN MATCHED THEN UPDATE
SET a.in_correct = NVL(in_correct, 'Y');
UPDATE:
A more "general" command (for non null values):
MERGE INTO table_1 a USING
(SELECT * from table_2) b
ON ( a.row_id = b.row_id)
WHEN MATCHED THEN UPDATE
SET a.in_correct = case
when in_correct = 'valuetobereplaced' then 'Y';
else in_correct;
end;

Resources