Update a column based on column from another table - oracle

Why does my update statement say - "cannot insert null into gitb_auto_debit_upload.status". The second query returned a record where the column process_status was having 'P' as its value.
Update gitb_auto_debit_upload a
set status = (select nvl(process_status,'O') from gitb_daily_log b
where b.interface_code = 'PHP661OW'
and b. process_ref_no = '4708'
and a.refno = b.external_ref_no
and a.recordno = b. seq_no
) ;
select * from gitb_auto_debit_upload a, gitb_daily_log b where b.interface_code = 'PHP661OW'
and b. process_ref_no = '4708'
and a.refno = b.external_ref_no
and a. recordno = b. seq_no

The error message comes from a record in gitb_auto_debit_upload for which the select (the one inside the update) statement returns no row.
Your update statement processes all records of gitb_auto_debit_upload.
Your select (the one you use to test the status value) statement only those records for which a record in gitb_daily_log exists.
You need to change the update statement to either only update those rows for whicht the select return a row or to place the NVL() around the select.

Related

Getting ORA-00001 unique constraint violated error when calling a trigger

create or replace TRIGGER "DB"."TRIG_PERIOD_TRUANCY_INS_UPD"
AFTER UPDATE OR INSERT
ON AT_PERIOD_ATTENDANCE_RECORDS
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
BEGIN
IF UPDATING THEN
delete at_period_truancy where period_attendance_records_id = :old.period_attendance_records_id;
END IF;
insert into at_period_truancy (period_attendance_records_id, district_number, school_id, student_id, calendar_date, school_year, minutes)
select :new.period_attendance_records_id, :new.district_number, :new.school_id, :new.student_id, :new.calendar_date, :new.school_year,
(case when :new.attendance_status = 'A' then period.end_time - period.begin_time
when coalesce(:new.tardy_time_in_time, period.begin_time) - period.begin_time >
period.end_time - coalesce(:new.tardy_time_out_time, period.end_time)
then coalesce(:new.tardy_time_in_time, period.begin_time) - period.begin_time
else period.end_time - coalesce(:new.tardy_time_out_time, period.end_time) end)*24*60
from ca_calendar cal
inner join ca_school_calendar calendar
on (cal.district_number = calendar.district_number
and cal.calendar_id = calendar.calendar_id )
inner join sc_class_meeting_pattern meeting
on (calendar.cycle_day_cd = meeting.cycle_day_cd)
inner join sc_class class
on (class.school_scheduling_param_id = meeting.school_scheduling_param_id
and class.class_id = meeting.class_id)
inner join sc_period_info period
on (meeting.school_scheduling_param_id = period.school_scheduling_param_id
and meeting.period = period.period)
where :new.district_number = cal.district_number
and cal.is_active_ind = 1
and :new.school_id = cal.school_id
and :new.school_year = cal.school_year
and :new.calendar_type_cd = cal.calendar_type_cd
and :new.track_number = cal.track_number
and :new.calendar_date = calendar.calendar_date
and :new.school_id = class.school_id
and :new.class_id = class.class_id
and 1 in (select use_in_truancy_report_ind
from enum_at_absence_reason_code
where district_number = :new.district_number
and school_id = :new.school_id
and value = :new.absence_reason_code
union all
select use_in_truancy_report_ind
from enum_at_tardy_reason_code
where district_number = :new.district_number
and school_id = :new.school_id
and value = :new.tardy_reason_code);
END TRIG_PERIOD_TRUANCY_INS_UPD;
This is the trigger that I am using. When calling the update statement this trigger is getting invoked and when I pass tardy_reason_code as UN this error is happening. It executes without any issues if I pass tardy_reason_code with different values.
Trigger is inserting into at_period_truancy tables.
As Oracle raises ORA-00001 (unique constraint violated), it means that you're trying to insert primary key value which already exists in the table.
You didn't post create table statement so it is difficult to guess which columns make the primary key, but - you should know it so check which values you already have in there, compare that to values currently being inserted and you'll know what to do.
Maybe you'll have to modify primary key (add other columns? Abandon idea of current primary key and using a sequence (or identity column)) or the way you're inserting values into the table.

UPDATE TABLE T1 SET COLUMN= SELECT 0 FROM TABLE T1

UPDATE SCPOMGR.DFUVIEW D
SET D.UDC_NEWDFU = (SELECT (CASE WHEN D1.UDC_CREATIONDATE > ADD_MONTHS (TRUNC(SYSDATE),3)
THEN 1
ELSE 0
END)
FROM SCPOMGR.DFUVIEW D1, SCPOMGR.UDT_GEN_PARAM G
WHERE D.DMDUNIT = D1.DMDUNIT
AND D.DMDGROUP = D1.DMDGROUP
AND D.LOC = D1.LOC
AND G.REGION=VREGION
AND G.JDA_CODE=SUBSTR(D1.DMDUNIT,-2,2)
);
WHAT WILL A SELECT 0 DO?
WILL IT SELECT NO ROWS AND UPDATE THE COLUMN WITH A NULL?
On the right-hand side of the assignment (the value you want to UPDATE) you have a SELECT statement with a CASE expression. There is a subquery (a join with several additional filters). The SELECT statement will return exactly as many rows as there are in the join and satisfy all the additional filters. For some of those rows the SELECT statement will return 1 and for the others, 0.
Do you expect that the subquery (the join with many WHERE conditions) will return exactly one row, then you check the CREATIONDATE and based on that, you update the value to 1 or 0?
In principle, the SELECT statement may return more than one row - in which case you will get a different error message, something about a scalar query (one that is supposed to be scalar, anyway) returning more than one row.
It is also possible that the subquery returns no rows at all - in that case the SELECT statement will return no rows at all, and in such cases the UPDATE means "assign NULL to the column of the left-hand side of the assignment". This is what seems to have happened here.
That is no reason to raise an exception. However, you would get an exception if the column (UDC_NEWDFU) has a NOT NULL constraint.
Since the CASE expression can ONLY return 0 or 1, never NULL, the ONLY way where a NULL assignment is possible is when the subquery (the join with many conditions) returns no rows. In one of the Comments you said that subquery does return rows. I don't believe you. If it does return rows, then I don't believe you that you have an update to NULL being attempted.

Update statement with joins in Oracle

I need to update one column in table A with the result of a multiplication of one field from table A with one field from table B.
It would be pretty simple to do this in T-SQL, but I can't write the correct syntax in Oracle.
What I've tried:
UPDATE TABLE_A
SET TABLE_A.COLUMN_TO_UPDATE =
(select TABLE_A.COLUMN_WITH_SOME_VALUE * TABLE_B.COLUMN_WITH_PERCENTAGE
from TABLE_A
INNER JOIN TABLE_B
ON TABLE_A.PRODUCT_ID = TABLE_B.PRODUCT_ID
AND TABLE_A.SALES_CHANNEL_ID = TABLE_B.SALES_CHANNEL_ID)
WHERE TABLE_A.MONTH_ID IN (201601, 201602, 201603);
But I keep getting errors. Could anybody help me, please?
I generally prefer to use the below format for such cases since this will ensure there's no update performed if there's no data in the table(query extracted temp table) whereas in the above solution provided by Brian Leach will update the new value as null if there's no record present in the 2nd table but exists in the first table.
UPDATE
(
select TABLE_A.COLUMN_TO_UPDATE
, TABLE_A.PRODUCT_ID
, TABLE_A.COLUMN_WITH_SOME_VALUE * TABLE_B.COLUMN_WITH_PERCENTAGE as value
from TABLE_A
INNER JOIN TABLE_B
ON TABLE_A.PRODUCT_ID = TABLE_B.PRODUCT_ID
AND TABLE_A.SALES_CHANNEL_ID = TABLE_B.SALES_CHANNEL_ID
AND TABLE_A.MONTH_ID IN (201601, 201602, 201603)
) DATA
SET DATA.COLUMN_TO_UPDATE = DATA.value;
This solution can cause key preserved value issues which shouldn't be an issue here since i expect a single row in both the tables for one product(ID).
More on Key Preserved table concept in inner join can be found here
https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:548422757486
#Jayesh Mulwani raiesed a valid point, this will set the value to null if there is no matching record. This may or may not be the desired result. If it isn't, and no change is desirect, you can change the select statement to:
coalesce((SELECT table_b.column_with_percentage
FROM table_b
WHERE table_a.product_id = table_b.product_id AND table_a.sales_channel_id = table_b.sales_channel_id),1)
If this is the desired outcome, Jayesh's solution will be more efficient as it will only update matching records.
UPDATE table_a
SET table_a.column_to_update = table_a.column_with_some_value
* (SELECT table_b.column_with_percentage
FROM table_b
WHERE table_a.product_id = table_b.product_id
AND table_a.sales_channel_id = table_b.sales_channel_id)
WHERE table_a.month_id IN (201601, 201602, 201603);

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)

Assignment in Hive query

I have below query in which i need to assign one table column value to another table column.
Query:
SELECT A.aval,B.bval,B.bval1 FROM A JOIN B ON (A.aval = B.bval)
How do I assign one table column value to another table column in Hive?
Have tried
SELECT A.aval,B.bval,B.bval1, A.aval = B.bval1 FROM A JOIN B ON (A.aval = B.bval)
In results:
A.aval = B.bval1, returning false since its not assigning to A.aval.
I guess you want to write in a table ?
So You have to create a table (for example C) which contains all the fields you need.
And then you do :
INSERT [OVERWRITE] INTO TABLE C
SELECT A.aval,B.bval,B.bval1, A.aval
FROM A
JOIN B ON (A.aval = B.bval)
The result of the select will be inserted in the table C
insert overwrite table c SELECT A.aval,B.bval,B.bval1 FROM A JOIN B ON (A.aval = B.bval)

Resources