Q:

Merge statement error when nulls in the column

I have a merge statement 
DESTINMATION TABLE =~ DST
SOURCE TABLE =~ SRC
MERGE DST
USING (SELECT * FROM SRC WHERE <Some_Condition>) SRC
ON SCR.COL1 = DST.COL1 OR (SRC.COL1 IS NULL AND DST.COl1 IS NULL) AND 
ON SCR.COL2 = DST.COL2 OR (SRC.COL2 IS NULL AND DST.COl2 IS NULL) AND 
ON SCR.COL3 = DST.COL3 OR (SRC.COL3 IS NULL AND DST.COl3 IS NULL) AND 
ON SCR.COL4 = DST.COL4 OR (SRC.COL4 IS NULL AND DST.COl4 IS NULL) 
WHEN MATCHED UPDATE DST
WHEN NOT MATCHED BY SOURCE THEN UPDATE DST
WHEN NOT MATCHED INSERT IN DST

Table Structure
Source

Column1 Column2 Column3 Column4
A        A       NULL    NULL
B        B       NULL    NULL

Destination

Column1 Column2 COlumn3 Column4 Column5

Error
The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.
But when I am using below query (i.e. using only those columns which has some values and not null values like Column3 and Column 4 in SRC) Everything works fine
MERGE DST
    USING (SELECT * FROM SRC WHERE <Some_Condition>) SRC
    ON SCR.COL1 = DST.COL1 OR (SRC.COL1 IS NULL AND DST.COl1 IS NULL) AND 
    ON SCR.COL2 = DST.COL2 OR (SRC.COL2 IS NULL AND DST.COl2 IS NULL) 
    WHEN MATCHED UPDATE DST
    WHEN NOT MATCHED BY SOURCE THEN UPDATE DST
    WHEN NOT MATCHED INSERT IN DST

EDIT: Replicate the scenario
SOURCE TABLE
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[tblSource](
    [Column1] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column2] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column3] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column4] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column5] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

DESTINATION TABLE
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[tblDestination](
    [Column1] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column2] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column3] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column4] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column5] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column6] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

DATA IN SOURCE
INSERT [dbo].[tblSource] ([Column1], [Column2], [Column3], [Column4], [Column5]) VALUES (N'A', N'A', NULL, NULL, NULL)
INSERT [dbo].[tblSource] ([Column1], [Column2], [Column3], [Column4], [Column5]) VALUES (N'B', N'B', NULL, NULL, NULL)

Destination is empty
Merge Statement
MERGE dbo.tblDestination DST
USING (SELECT * FROM dbo.tblSource) SRC
ON DST.Column1 = SRC.Column1 OR (DST.Column1 IS NULL AND SRC.Column1 IS NULL) AND
DST.Column2 = SRC.Column2 OR (DST.Column2 IS NULL AND SRC.Column2 IS NULL) AND
DST.Column3 = SRC.Column3 OR (DST.Column3 IS NULL AND SRC.Column3 IS NULL) AND
DST.Column4 = SRC.Column4 OR (DST.Column4 IS NULL AND SRC.Column4 IS NULL) AND
DST.Column5 = SRC.Column5 OR (DST.Column5 IS NULL AND SRC.Column5 IS NULL)

WHEN MATCHED THEN
        UPDATE SET COLUMN5 = 'A'
WHEN NOT MATCHED BY SOURCE THEN
        UPDATE SET Column5 = 'B'
WHEN NOT MATCHED THEN
        INSERT (Column1, Column2, Column3, Column4, Column5)
        VALUES (Column1, Column2, Column3, Column4, Column5) ;

Run it two times to see the error.
Now truncate the destination table
Now the same query but having only those columns which has data
MERGE dbo.tblDestination DST
USING (SELECT * FROM dbo.tblSource) SRC
ON DST.Column1 = SRC.Column1 OR (DST.Column1 IS NULL AND SRC.Column1 IS NULL) AND
DST.Column2 = SRC.Column2 OR (DST.Column2 IS NULL AND SRC.Column2 IS NULL) 

WHEN MATCHED THEN
        UPDATE SET COLUMN5 = 'A'
WHEN NOT MATCHED BY SOURCE THEN
        UPDATE SET Column5 = 'B'
WHEN NOT MATCHED THEN
        INSERT (Column1, Column2, Column3, Column4, Column5)
        VALUES (Column1, Column2, Column3, Column4, Column5) ;

This is working absouletly fine, you can run it as many times you want to run. 

A:

It is a matter of Operator Precedence.
DST.Column1 = SRC.Column1 OR (DST.Column1 IS NULL AND SRC.Column1 IS NULL) .... will match all rows where DST.Column1 = SRC.Column1 regardless of the values in the other columns.
You need to add some parentheses around the OR:ed conditions to override the default precedence.
MERGE dbo.tblDestination DST
USING (SELECT * FROM dbo.tblSource) SRC
ON (DST.Column1 = SRC.Column1 OR (DST.Column1 IS NULL AND SRC.Column1 IS NULL)) AND
   (DST.Column2 = SRC.Column2 OR (DST.Column2 IS NULL AND SRC.Column2 IS NULL)) AND
   (DST.Column3 = SRC.Column3 OR (DST.Column3 IS NULL AND SRC.Column3 IS NULL)) AND
   (DST.Column4 = SRC.Column4 OR (DST.Column4 IS NULL AND SRC.Column4 IS NULL)) AND
   (DST.Column5 = SRC.Column5 OR (DST.Column5 IS NULL AND SRC.Column5 IS NULL))

WHEN MATCHED THEN
        UPDATE SET COLUMN5 = 'A'
WHEN NOT MATCHED BY SOURCE THEN
        UPDATE SET Column5 = 'B'
WHEN NOT MATCHED THEN
        INSERT (Column1, Column2, Column3, Column4, Column5)
        VALUES (Column1, Column2, Column3, Column4, Column5) ;

