SSIS merge join only when left table has null columns - sql-server

I want to achieve this merge statement using SSIS. I know this can be achieved using a merge join in SSIS but I am not sure if I can fit COALESCE statement anywhere. I wanted merge to happen between two tables only when the target table has NULL records.
MERGE TargetTable AS TARGET
USING SourceTable AS SOURCE
ON ISNULL(TARGET.ColA, '') = ISNULL(SOURCE.ColA, '')
AND ISNULL(TARGET.ColB, '') = ISNULL(SOURCE.ColB, '')
WHEN MATCHED THEN UPDATE SET
TARGET.ColC = COALESCE(TARGET.ColC, SOURCE.ColC)
TARGET.ColD = COALESCE(TARGET.ColD, SOURCE.ColD)
TARGET.ColE = COALESCE(TARGET.ColE, SOURCE.ColE)
WHEN NOT MATCHED [BY TARGET] THEN INSERT
(ColA, ColB, ColC, ColD, ColE)
Values(SOURCE.ColA, SOURCE.ColB, SOURCE.ColC, SOURCE.ColD, SOURCE.ColE)

As mentioned in the comments, you can simply use derived columns transformations to achieve the ISNULL() and COALESCE() functions.
There are two approaches:
Using REPLACENULL() function:
REPLACENULL(ColA,"")
Using the conditional operator ? : with the ISNULL() function:
ISNULL([ColA]) == True ? "" : [ColA]

Related

What is the right syntax to create a table in sql server based on SELECT query

I have created a simple select query looks like a vlookup function in excel as the below query
SELECT [myDB].[dbo].[intrafreq_cell].[st_umts_hua_intra_relation_key]
,[myDB].[dbo].[umts_df_relation].[cell_name]
,[myDB].[dbo].[umts_df_relation].[n_cell_name]
,CASE
WHEN [myDB].[dbo].[umts_df_relation].[st_umts_df_relation_key] IS NULL
THEN 'FALSE'
ELSE 'TRUE'
END
FROM [myDB].[dbo].[intrafreq_cell]
LEFT OUTER JOIN [myDB].[dbo].[umts_df_relation] ON [myDB].[dbo].[intrafreq_cell].[st_umts_hua_intra_relation_key] = [myDB].[dbo].[umts_df_relation].[st_umts_df_relation_key]
WHERE [myDB].[dbo].[umts_df_relation].[st_umts_df_relation_key] = 'FALSE'
Now I need to create a table based on this query that contains the same columns but create a new column for the column which contains TRUE & FALSE by calling this column missing_rel_in_df
I just want to use CREATE TABLE query instead of SELECT TABLE query based on this SELECT query
You just need to add a INTO at the end of the SELECT part to indicate that you want to create a new table with the result of that query.
SELECT
[myDB].[dbo].[intrafreq_cell].[st_umts_hua_intra_relation_key]
,[myDB].[dbo].[umts_df_relation].[cell_name]
,[myDB].[dbo].[umts_df_relation].[n_cell_name]
,CASE WHEN [myDB].[dbo].[umts_df_relation].[st_umts_df_relation_key] IS NULL THEN 'FALSE' ELSE 'TRUE' END AS missing_rel_in_df
INTO MY_NEW_TABLE
FROM [myDB].[dbo].[intrafreq_cell]
LEFT OUTER JOIN [myDB].[dbo].[umts_df_relation] ON [myDB].[dbo].[intrafreq_cell].[st_umts_hua_intra_relation_key] = [myDB].[dbo].[umts_df_relation].[st_umts_df_relation_key]
WHERE [myDB].[dbo].[umts_df_relation].[st_umts_df_relation_key] = 'FALSE'
PS: remember to set the name "missing_rel_in_df" for your calculated column, so that column will have this name on the new table.
You can use SELECT . . . INTO :
SELECT . . .
INTO <table_name>
FROM [myDB].[dbo].[intrafreq_cell] LEFT OUTER JOIN
[myDB].[dbo].[umts_df_relation]
ON [myDB].[dbo].[intrafreq_cell].[st_umts_hua_intra_relation_key] = [myDB].[dbo].[umts_df_relation].[st_umts_df_relation_key]
WHERE [myDB].[dbo].[umts_df_relation].[st_umts_df_relation_key] = 'FALSE';
By this way, you will have auto created table with required data returned from select statement. In SQL Server CREATE TABLE statement is independent work. You can't merge it with select statement.
If you don't want data, only schema then you can add where clause with false condition such as :
WHERE 1 = 0;
You can also use Into as shown below.
Select * into <NewTablenameTobeCreated> from <oldAvailableTablename>
You can pass condition like where condition, aggregate function, top
n, etc. while selecting the record.
It will be easy to understand if you will separate the into command in two parts.
The first part will be the columns for which you want to create the table and another will be the data source column like a normal select statement.

SQL Server : using MERGE statement to update two tables

I am trying to use a MERGE statement to update 2 tables using a single source (CTE). It works when I use only 1 merge, but when I add the 2nd one, it returns an error:
Msg 208, Level 16, State 1, Procedure mn_SeoUrl_UpdateBulk, Line 46
Invalid object name 'cte'.
Is it possible to update 2 tables with a merge? If it is possible, I am doing it incorrectly and I hope someone can show me what is the correct method of doing this.
Any help is much appreciated.
Thank you.
Here is my failing code (false col names):
WITH cte AS
(
SELECT
[u].[col1], [u].[col2], [u].[col3],
CASE
WHEN [u].[col1] LIKE 'L%'
THEN 'c/' + [u].[col2] + '/' + [u].[col3]
WHEN [u].[col1] LIKE 'M%'
THEN 'm/' + [u].[col2] + '/' + [u].[col3]
END [col4]
FROM
(SELECT
[st1].[col1], [st1].[col2], [st1].[col3]
FROM
[dbo].[sourcetable1] [st1]
INNER JOIN
[dbo].[sourcetable2] [st2] ON [st1].[ID] = [st2].[ID]
WHERE
[pd].[col2] <> 0) [u]
)
MERGE [dbo].[table1] AS [Target]
USING [cte] AS [Source] ON [Target].[ID] = [Source].[ID]
WHEN MATCHED THEN
UPDATE
SET [Target].[col] = [Source].[col]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([col])
VALUES ([Source].[col]);
MERGE [dbo].[tabl2] AS [Target]
USING [cte] AS [Source] ON [Target].[id] = [Source].[id]
WHEN MATCHED THEN
UPDATE
SET [Target].[col] = [Source].[col]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([col])
VALUES ([Source].[col]);
END;
Is it possible to update 2 tables with a merge?
No, it is not possible to update two tables with a single merge. You have to do two separate merge statements.
And as others have pointed out in comments, a single CTE can only be used for one statement, so if you do two merge statements, they can't share the same CTE. My suggestion would be to use your CTE query to populate a table variable. Then you can use the same table variable in two merge statements.

An action of type 'INSERT' is not allowed in the 'WHEN MATCHED' clause of a MERGE statement

I want to perform a "soft delete". I.e. insert a new entry when matched and when not matched just insert an entry.
For example:
MERGE TargetTable AS targetT
USING SourceTable AS sourceT ON sourceT.Npi = targetT.Npi
WHEN MATCHED AND IsNull(targetT.SPI, '') <> '' THEN
UPDATE SET targetT.Isdelete = 1 --Update Only One Column
--And also insert a new row
WHEN NOT MATCHED
--Perform insert operation
The merge statement will not work this way. You would have to do it the old fashioned way (using a stored procedure would work).
It looks like you are trying to create an archive record. If this is true I suggest you use the merge as it is intended to be used and use an after update trigger to do your auditing needs.

How can I use SQL MERGE to upsert single row based on Id, without a source set

There are a number of questions on the proper use of the MERGE statement in SQL Server. They all use a table/set reference for the merge. Is this table reference necessary?
In my case I have a sproc with two parameters #myId and #myValue
I simply want an UPSERT into MyTable based on the column [MyId]
It seems strange that I would have to create a set with
USING (SELECT #myId AS myId) AS source
to proceed with the MERGE (upsert). Is this the only way?
EDIT: voted to close my own question as exact duplicated... but I think the other question's title made it difficult to find.
You can also use this syntax:
merge into MyTable mt
using (values (#myId, #myValue)) t(id, value) on mt.Id = t.id
when not matched then insert /* ... */
You're always going to need a set of some kind.

Moving data between fields in destination table in T-SQL MERGE

I have a SQL MERGE statement that does an UPDATE if a value exists (and an INSERT if it does). I'd like to record the last few "historical" values in the row when an UPDATE happens, sort of like this:
MERGE into desttable as dest
USING sourcetable as src
on src.ref = dest.ref
WHEN MATCHED THEN
UPDATE SET dest.oldvalue3=dest.oldvalue2,
dest.oldvalue2=dest.oldvalue1,
dest.oldvalue1=dest.value,
dest.value=src.newvalue
WHEN NOT MATCHED THEN
INSERT ...
... so essentially, the existing "value" is shuffled down to "oldvalue1", "oldvalue1" becomes "oldvalue2" etc. However, when I run this, every column gets set to "value" - the UPDATE statement is obviously setting all the fields at once. Is there any way to achieve what I'm trying to do?
You can left outer join desttable in the using clause and use columns from desttable as source to the update.
MERGE INTO desttable AS dest
USING (SELECT s.ref,
s.newvalue,
d.oldvalue2,
d.oldvalue1,
d.value
FROM sourcetable AS s
LEFT OUTER JOIN desttable AS d
ON s.ref = d.ref) AS src
ON src.ref = dest.ref
WHEN MATCHED THEN
UPDATE SET dest.oldvalue3=src.oldvalue2,
dest.oldvalue2=src.oldvalue1,
dest.oldvalue1=src.value,
dest.value=src.newvalue
;
https://data.stackexchange.com/stackoverflow/q/114412/

Resources