Oracle SQL merge does not insert when the destination table is empty - sql

I want to update/insert records in main schema from working schema using a merge statement. The piece of code that does the merge is as below.
MERGE INTO ods_workday.ORGANIZATION x
USING (SELECT organization_id, organization_code, organization_type, organization_name, organization_description,
inactive, manager, leadership_role_assignee, organization_owner, supervisory_organization,
primary_site_reference, inactive_date, organization_subtype
FROM ods_workday_w.ORGANIZATION) y
ON (x.ORGANIZATION_ID = y.ORGANIZATION_ID)
WHEN MATCHED THEN
UPDATE SET x.organization_code = y.organization_code,
x.organization_type = y.organization_type,
x.organization_name = y.organization_name,
x.organization_description = y.organization_description,
x.inactive = y.inactive,
x.manager = y.manager,
x.leadership_role_assignee = y.leadership_role_assignee,
x.organization_owner = y.organization_owner,
x.supervisory_organization = y.supervisory_organization,
x.primary_site_reference = y.primary_site_reference,
x.inactive_date = y.inactive_date,
x.organization_subtype = y.organization_subtype,
x.UPDATE_TIME_STAMP = CURRENT_TIMESTAMP
WHERE x.organization_code <> y.organization_code OR
x.organization_type <> y.organization_type OR
x.organization_name <> y.organization_name OR
x.organization_description <> y.organization_description OR
x.inactive <> y.inactive OR
x.manager <> y.manager OR
x.leadership_role_assignee <> y.leadership_role_assignee OR
x.organization_owner <> y.organization_owner OR
x.supervisory_organization <> y.supervisory_organization OR
x.primary_site_reference <> y.primary_site_reference OR
x.inactive_date <> y.inactive_date OR
x.organization_subtype <> y.organization_subtype
WHEN NOT MATCHED THEN
INSERT(x.organization_id, x.organization_code, x.organization_type, x.organization_name,
x.organization_description, x.inactive, x.manager, x.leadership_role_assignee,
x.organization_owner, x.supervisory_organization, x.primary_site_reference, x.inactive_date,
x.organization_subtype, x.UPDATE_TIME_STAMP)
VALUES(y.organization_id, y.organization_code, y.organization_type, y.organization_name,
y.organization_description, y.inactive, y.manager, y.leadership_role_assignee,
y.organization_owner, y.supervisory_organization, y.primary_site_reference, y.inactive_date,
y.organization_subtype, CURRENT_TIMESTAMP);
The code works fine when the destination table has records, but when the destination table is empty (has zero records than the merge).
Is there a way we can make the merge statement to work, when there are no records to start with in the target schema.
The Oracle database is 11g.

This is resolved.
I had not added a foreign key constraint present in source table because of which insert on zero records was not working.

Related

ERROR: CASE types integer and boolean cannot be matched

I'm getting the abovementioned error when trying to execute an update query. See below schema for reference.
The goal of the query is to update the capital row of the client table to be the same as the solde row of the compte table if the client has a compte. If they do not, the value of capital must be 0. I tried the below query and the error message mentioned in the title appeared.
UPDATE client
SET capital = (
SELECT
CASE
WHEN client_compte.compte_num IS NOT NULL THEN client.capital = compte.solde
ELSE 0
END
FROM compte
JOIN client_compte ON compte.compte_num = client_compte.compte_num
JOIN client ON client_compte.client_id = client.client_id);
Any help solving this error?
The message seems quite clear -- the types of the columns do not match. However, your update is malformed because of the two references to client. Presumably, you intend:
UPDATE client cl
SET capital = (CASE WHEN cc.compte_num IS NOT NULL
THEN cc.solde
ELSE 0
END)
FROM client_compte cc JOIN
compe c
ON c.compte_num = cc.compte_num;
WHERE cc.client_id = cl.client_id;
That fixes the error but is not exactly what you want. I think a correlated subquery is better:
UPDATE client cl
SET capital = COALESCE((SELECT cc.solde
FROM client_compte cc JOIN
compte c
ON c.compte_num = cc.compte_num
WHERE cc.client_id = cl.client_id
), 0
);

Most effifient way to update one column from 3 columns

Is this the most efficient way to update one single column from three different columns?
UPDATE TBL_FR2052A_TPOS_HIST_SPLIT
SET REPORTABLE_AMOUNT = ISNULL(PRINCIPAL,0)
UPDATE TBL_FR2052A_TPOS_HIST_SPLIT
SET REPORTABLE_AMOUNT = ISNULL(INTEREST,0)
UPDATE TBL_FR2052A_TPOS_HIST_SPLIT
SET REPORTABLE_AMOUNT = ISNULL(RAW_DATA_AMOUNT,0)
I am using SQL Server. Thanks!
Looks like COALESCE() would help
UPDATE TBL_FR2052A_TPOS_HIST_SPLIT
SET REPORTABLE_AMOUNT = COALESCE(ROW_DATA_AMOUNT, INTEREST, PRINCIPAL, 0)
REPORTABLE_AMOUNT will then be updated with the first value in the COALESCE() that is not null.
Please try SQL : Case - When - End if you are checking Null for update fields.
Egs:
UPDATE TBL_FR2052A_TPOS_HIST_SPLIT
SET REPORTABLE_AMOUNT =
case when ISNULL(PRINCIPAL,0) <> 0 then PRINCIPAL
case when ISNULL(INTEREST,0) <> 0 then INTEREST
case when ISNULL(RAW_DATA_AMOUNT,0) <> then RAW_DATA_AMOUNT
else 0 --default value
End
Regards
Abdul

Converting the sybase stuff function in to oracle

Sybase query :
UPDATE #horizCallSign SET
effDaysZ = STUFF( effDaysZ, csd.day+shift1, 1, '1')
FROM #callSignTbl csd
WHERE csd.legId1 = #horizCallSign.legId1
AND csd.legId2 = #horizCallSign.legId2
AND day = 28
Oracle Query :
UPDATE TEMP_HORIZ_CALL_SIGN
SET eff_Days_Z = REPLACE( eff_days_Z,csd.day+shift1, '1')
FROM temp_call_sign_table1 csd
WHERE csd.leg_Id1 = temp_horiz_Call_Sign.leg_Id1
AND csd.leg_Id2 = horiz_Call_Sign.leg_Id2
AND day = 28
In Oracle, we have changed the column names with having "_" in them.
temp_call_sign_table1 and TEMP_HORIZ_CALL_SIGN are global temporary tables
created for Oracle in place of sybase temp tables with on commit preserve
rows.
We are converting sybase DB to Oracle DB. When I execute the above query in oracle it says QL Error: ORA-00933: SQL command not properly ended.
Please help.
There was an issue with your table name on line 5, this is easily avoided by using aliases.
Also, you can't use FROM in Oracle without a SELECT. Thus a sub-query must be used in this instance. For example...
UPDATE TEMP_HORIZ_CALL_SIGN hcs
SET eff_Days_Z =
(SELECT
REPLACE(eff_days_Z,csd.day+shift1, '1')
FROM temp_call_sign_table1 csd
WHERE csd.leg_Id1 = hcs.leg_Id1
AND csd.leg_Id2 = hcs.leg_Id2
AND day = 28)
(Not tested)
Your are off on your aliasing. Also, consider using INNER JOINS instead.
UPDATE THCS
SET eff_Days_Z = REPLACE( eff_days_Z,csd.day+shift1, '1')
FROM temp_call_sign_table1 csd , TEMP_HORIZ_CALL_SIGN THCS, horiz_Call_Sign HCS
WHERE csd.leg_Id1 = THCS.leg_Id1
AND csd.leg_Id2 = HCS.leg_Id2
AND day = 28
In Oracle, You can use MERGE INTO.
MERGE INTO temp_horiz_call_sign m
using (SELECT leg_id1,
leg_id2,
eff_days_z,
day + shift1 plushift1
FROM temp_call_sign_table1
WHERE day = 28) r
ON ( r.leg_id1 = m.leg_id1
AND r.leg_id2 = m.leg_id2 )
WHEN matched THEN
UPDATE SET m.eff_days_z = Replace(m.eff_days_z, r.plushift1, '1');

How to not update null value into a column when it already have a value in SQL Server query

How can I not update the null value into a column when it already have a value in SQL Server query in the query prepared in Mule? The payload contains the result set from Data weave. While updating, I want to check whether the updating value is null or not, in case of it "not null" then only value should be updated.
Query is:
UPDATE dbo.ix_str_store
SET NAME = '#[payload.Site.Name]',
ADDRESS1 = '#[payload.Site.Address1]',
ADDRESS2 = '#[payload.Site.Address2]',
ADDRESSCITY = '#[payload.Site.AddressCity]',
ADDRESSSTATE = '#[payload.Site.AddressState]',
ADDRESSPOSTALCODE = '#[payload.Site.AddressPostalCode]',
ADDRESSCOUNTRY = '#[payload.Site.AddressCountry]',
EMAIL = '#[payload.Site.Email]',
PHONE = '#[payload.Site.Phone]',
FAX = '#[payload.Site.Fax]',
REGION = '#[payload.Site.Region]',
COMPANY = '#[payload.Site.Company]',
DESC1 = '#[payload.Site.Desc1]',
DESC2 = '#[payload.Site.Desc2]',
DESC7 = '#[payload.Site.Desc7]',
DESC8 = '#[payload.Site.Desc8]',
VALUE1 = #[payload.Site.Value1],
VALUE2 = #[payload.Site.Value2],
DBTIME = CURRENT_TIMESTAMP,
DBSTATUS = 1
WHERE
STORENUMBER = #[payload.Site.StoreNumber]
try it's
isnull(new_value,old_value)
In that case, instead of using insert into (...) values(...) construct ; use insert into .. select from construct like
insert into table (..)
select ..,
case when new_col_val is not null then new_col_val else old_col_val end
from ...
(OR) you can as well use COALESCE() function instead of CASE expression saying coalesce(new_col_val, old_col_val)

conditional handling of update sql script depending on input parameter

I am new to SQL and using Oracle 11. I need to write a sql script which uses different update command based on whether the input param is null or not null.
I need something like this
['&' followed by the parameter name is the way i see parameters being used in other such
script for our project]
IF &PRG_ID IS NULL
UPDATE PROGRAM_TABLE P SET HANDLED_IND = 'Y' WHERE EXISTS
(SELECT 1 FROM HANDLED_PROGRAM H WHERE H.PROGRAM_ID = P.PROGRAM_ID);
ELSE
UPDATE PROGRAM_TABLE P SET HANDLED_IND = 'Y' WHERE
P.PROGRAM_ID = &PRG_ID AND EXISTS
(SELECT 1 FROM HANDLED_PROGRAM H WHERE H.PROGRAM_ID = P.PROGRAM_ID);
END IF;
Something like (is not tested):
UPDATE PROGRAM_TABLE P SET HANDLED_IND = 'Y' WHERE EXISTS
(SELECT 1 FROM HANDLED_PROGRAM H WHERE H.PROGRAM_ID = P.PROGRAM_ID)
AND (&PRG_ID IS NULL OR P.PROGRAM_ID = &PRG_ID);
But take into account this change may lead to the performance degradation for the case when PRG_ID has definite value.