Does Oracle MERGE Handles Table Join Automatically? - sql

I am new to ORACLE MERGE Command.
I intend to insert a row into a target table based on a source table data.
The source table has Foreign Key Relation to Target Table. Column1 and Column2 in source table must exist to allow a row with those values in Target Table.
My Merge query looks like this.
MERGE into TARGET_TABLE target
USING (
Select column1, column2 from SOURCE_TABLE where column3='somevalue'
) source
ON (
source.column1 is null or target.column4='anotherValue'
)
WHEN NOT MATCHED THEN INSERT (
target.column1,
target.column2,
target.column3,
target.column4
) VALUES (
source.column1,
source.column2,
'somevalue3',
'anotherValue'
)
It inserts one row and only when it finds that source.column1 is existing for the source.column3 value of 'somevalue' ie not null and,
there is no row in target table whose column1, column2 and column 4 have following values respectively
Same value of column1 in source table when column3 is 'someValue'
Same value of column2 in source table when column3 is 'someValue'
'anotherValue'
I need an explanation as to why it matches Point1 and Point2 above even though my MATCH conditions in 'ON' clause does not include them.
When I coded this I expected multiple rows to NOT MATCH the condition since there are many rows in target table where column4 does not has value anotherValue.
ATTEMPT TO ELABORATE # 1
TABLE 1 (SOURCE)
COL1 COL2 COL3
a1 a2 a3
TABLE 2 (TARGET)
COL1 COL2 COL3 COL4
No row
DESIRED Behavior:
Insert a row in TABLE 2
if source table has a row where COL3 = 'a3' and
if there is no row in target with col1 = a1 and col2 = a2 and col4 = b4
Data to be inserted in Target table is: col1 = a1, col2 = a2 and col4 = b4
OBSERVED BEHAVIOR
Matches the desired behavior above which surprised me. I wondered that I need to have an ON CLAUSE Like this
ON (
source.column1 is null or source.column1 != target.column1 or source.column2 != target.column2 or target.column4 = 'anotherValue'
)
Based on DEMorgan's law:
NOT (A and B) = NOT A or NOT B;
NOT (A OR B ) = NOT A and NOT B

Related

Rename category in the column in SQL Server

Here is the query
select col1
from table
col1 contains these category values:
A
B
C
NULL
How can I rename null category to D?
If you want to make the change permanent
UPDATE table
SET col1 = 'D'
WHERE col1 IS NULL
From then on you can simply query with ...
SELECT col1
FROM table
... to get the desired result.
If there is more than one row having a NULL in col1, you need to filter by a unique key, preferably by the primary key (which every table should have by the way). Let's say you have a table like
id (PK) col1
--- ----
1 'A'
2 'B'
3 'C'
4 NULL
5 NULL
then you can fix it with
UPDATE table SET col1 = 'D' WHERE id = 4;
UPDATE table SET col1 = 'E' WHERE id = 5;
unless you can calculate the new value from another column, e.g.:
UPDATE table
SET col1 = UPPER(LEFT(name, 1))
Try this : ISNULL( ) function is used to replace NULL value with another value
select isnull(col1,'D') as col1
from table
SQL Server uses ISNULL().
SELECT ISNULL(value_to_check, use_this_instead_if_valuetocheck_is_null)
For your code:
select ISNULL(col1, 'D') AS col_name
from table
However, this will happen across the board for this column. You can't use this to make a sequence, like D then E then F. Any NULL value you come across in this column will change to D.

Oracle: Select and Update at the same time

I have three tables:
Table-1: Column1 | Column2 | Column 3
Table-2: Column4 | Column5 | ColumnUpdate
Table-3: Column7 | Column8
I need to copy some rows from Table-2 to Table-3 based on some conditions with Table-1:
My insert-statement looks like this:
INSERT INTO Table-3 (
Column7,
Column8)
SELECT Table-2.COLUMN4, Table-2.COLUMN5
FROM Table-2 INNER JOIN Table-1
ON Table-2.COLUMN4 = TABLE-1.Column1;
However I want to update column: ColumnUpdate" (Table-2) of the selecting row to "1".
So I select some rows and immediately want to update a process column in that row as '1'.
I don't know how to do that. I saw some examples with "OUTPUT" clause or "UPDATE FOR" but I dont exactly know how to use them in my statement.
MERGE
INTO target_table t1
USING (SELECT col1, col2
FROM source_table
WHERE //conditions here) s1
ON (t1.id = s1.id)
WHEN MATCHED THEN
UPDATE SET column_update = '1'
WHEN NOT MATCHED THEN
INSERT (col1, col2)
VALUES (s1.col1, s1.col2)
WHERE (// condition here);
UPDATE
BEGIN
FOR temp_var IN (
SELECT * from table_a
WHERE table_a.col1 = table_b.col1)
LOOP
// INSERTING INTO TARGET TABLE
INSERT INTO table_b
VALUES(temp_var.col1, temp_var.col2);
// UPDATING SOURCE TABLE
UPDATE table_a
SET status = 'COPIED'
WHERE col1 = temp_var.col1;
END LOOP;
END;

Update target table only if its not null

I have a scenario, where we want to update 40 columns in oracle table. source is another oracle table.
They want to igonore the value of the column if it have null !!
example:
col1 col2 col3
1 null b
2 null 3
target table :
col1 col2 col3
1 a null
2 b null
after updted.
col1 col2 col3
1 a b
2 b 3
note : we have to upate only if its not null ..
any advise is appreciated.
update target_table tt
set (col1, col2, col3) = ( select nvl(st.col1,tt.col1),
nvl(st.col2,tt.col2),
nvl(st.col3,tt.col3)
from source_table st where st.primary_key = tt.primary_key )
where exists ( select null
from source_table st
where st.primary_key = tt.primary_key
and (st.col1 is not null
or st.col2 is not null
or st.col3 is not null) );
Obviously you have to determine what the primary key is. I used "primary_key" only as an instructive guide.
Try
MERGE INTO TARGET_TABLE t
USING SOURCE_TABLE s
ON (s.COL1 = t.COL1)
WHEN MATCHED THEN
UPDATE SET t.COL2 = NVL(t.COL2, s.COL2)
t.COL3 = NVL(t.COL3, s.COL3);
I'm assuming here the COL1 is the column to use to find matching rows in TARGET_TABLE and SOURCE_TABLE.
Share and enjoy.

how to select col1 value x and copy to new row with col1 value y,if run query again,should not copy again

how to copy rows to same table where select column1 value = 55 and to new row with column 1 value = 56, if we run query second time, it should not copy the old lines again
You could add a where clause to prevent a duplicate insert using not exists:
insert YourTable
(col1, col2, col3, ...)
select 56 -- New value
, col2
, col3
, ...
from YourTable
where col1 = 55 -- Old value
and not exists
(
select *
from YourTable
where col1 = 56 -- New value
)

Is there a SQL Statement that allows me to copy and insert existing rows but with one column change?

You might not understood what I want to ask from the title but ,here is the explanation.
I have a data in Oracle database table. What I wanted to do is insert a new data to the table. This new data is based on the existing data but I have to change the value of one columns. So if I have 10 rows in the database after the insertion i will have 20 rows but the new 10 rows contain the same data except on of the columns is changed.
E.g table before insertion a new data
Col1 Col2 Col3
a b AA
1 2 33
table after insertion a new data
Col1 Col2 Col3
a b **BB**
1 2 **44**
Provided that you can encode what the new value should be; yes.
INSERT INTO
myTable (
Col1,
Col2,
Col3
)
SELECT
Col1,
Col2, -- This is a specific example based on your comment.
Col3 + 6 -- This just adds 6 to the existing value, but any SQL
FROM -- could actually go here, such as a CASE statement...
myTable
So, the question becomes; Do you have rules that you can implement in SQL for calculating the new value for Col3?
The rules could be something basic like...
CASE WHEN Col3 = 'AA' THEN '**BB**'
WHEN Col3 = '33' THEN '**44**'
ELSE 'Unknown'
END,
Or you could have all the new values in another table and look them up using a join...
INSERT INTO
myTable (
Col1,
Col2,
Col3
)
SELECT
OldTable.Col1,
OldTable.Col2,
COALESCE(NewTable.Col3, 'Unknown')
FROM
myTable AS OldTable
LEFT JOIN
lookup AS NewTable
ON OldTable.Col1 = NewTable.Col1
AND OldTable.Col2 = NewTable.Col2
Or a whole bunch of other options.
It will depend on how you determine how to change the data. How do you know, for example, that AA should become BB or that 33 should become 44?
Something like this will work for the two cases you posted. You can adapt it to whatever rule you want by changing the CASE statement to compute the new value differently.
INSERT INTO table_name( col1, col2, col3 )
SELECT col1,
col2,
(CASE WHEN col3 = 'AA'
THEN 'BB'
WHEN col3 = '33'
THEN '44'
ELSE null
END)
FROM table_name;