diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
new file mode 100644
index a704045..322d511
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -257,6 +257,44 @@ transform_MERGE_to_join(Query *parse)
 							   bms_make_singleton(joinrti));
 
 	/*
+	 * Similarly, any non-target Vars in the join condition will be added to
+	 * the targetlist by preprocess_targetlist(), and so must be marked as
+	 * nullable by the join, for LEFT and FULL joins.  The same goes for Vars
+	 * in action quals, action targetlists and the RETURNING list.
+	 */
+	if (jointype == JOIN_LEFT || jointype == JOIN_FULL)
+	{
+		Bitmapset  *nontargetrels = NULL;
+
+		for (int i = 1; i < joinrti; i++)
+			if (i != parse->mergeTargetRelation)
+				nontargetrels = bms_add_member(nontargetrels, i);
+
+		parse->mergeJoinCondition =
+			add_nulling_relids(parse->mergeJoinCondition,
+							   nontargetrels,
+							   bms_make_singleton(joinrti));
+
+		foreach_node(MergeAction, action, parse->mergeActionList)
+		{
+			action->qual =
+				add_nulling_relids(action->qual,
+								   nontargetrels,
+								   bms_make_singleton(joinrti));
+
+			action->targetList = (List *)
+				add_nulling_relids((Node *) action->targetList,
+								   nontargetrels,
+								   bms_make_singleton(joinrti));
+		}
+
+		parse->returningList = (List *)
+			add_nulling_relids((Node *) parse->returningList,
+							   nontargetrels,
+							   bms_make_singleton(joinrti));
+	}
+
+	/*
 	 * If there are any WHEN NOT MATCHED BY SOURCE actions, the executor will
 	 * use the join condition to distinguish between MATCHED and NOT MATCHED
 	 * BY SOURCE cases.  Otherwise, it's no longer needed, and we set it to
diff --git a/src/test/regress/expected/merge.out b/src/test/regress/expected/merge.out
new file mode 100644
index 3d33259..ff0e167
--- a/src/test/regress/expected/merge.out
+++ b/src/test/regress/expected/merge.out
@@ -2689,6 +2689,27 @@ DETAIL:  drop cascades to table measurem
 drop cascades to table measurement_y2006m03
 drop cascades to table measurement_y2007m01
 DROP FUNCTION measurement_insert_trigger();
+--
+-- test for bug #18634
+--
+CREATE TABLE bug18634t (a int, b int);
+INSERT INTO bug18634t VALUES(1, 10), (2, 20);
+CREATE VIEW bug18634v AS
+  SELECT * FROM bug18634t WHERE EXISTS (SELECT 1 FROM bug18634t);
+CREATE TABLE bug18634s (a int, b int);
+INSERT INTO bug18634s VALUES (1, 2);
+MERGE INTO bug18634v t USING bug18634s s ON s.a = t.a
+WHEN MATCHED THEN UPDATE SET b = s.b
+WHEN NOT MATCHED BY SOURCE THEN DELETE;
+SELECT * FROM bug18634t;
+ a | b 
+---+---
+ 1 | 2
+(1 row)
+
+DROP TABLE bug18634t CASCADE;
+NOTICE:  drop cascades to view bug18634v
+DROP TABLE bug18634s;
 -- prepare
 RESET SESSION AUTHORIZATION;
 -- try a system catalog
diff --git a/src/test/regress/sql/merge.sql b/src/test/regress/sql/merge.sql
new file mode 100644
index 92163ec..020d22e
--- a/src/test/regress/sql/merge.sql
+++ b/src/test/regress/sql/merge.sql
@@ -1710,6 +1710,26 @@ SELECT * FROM new_measurement ORDER BY c
 DROP TABLE measurement, new_measurement CASCADE;
 DROP FUNCTION measurement_insert_trigger();
 
+--
+-- test for bug #18634
+--
+CREATE TABLE bug18634t (a int, b int);
+INSERT INTO bug18634t VALUES(1, 10), (2, 20);
+CREATE VIEW bug18634v AS
+  SELECT * FROM bug18634t WHERE EXISTS (SELECT 1 FROM bug18634t);
+
+CREATE TABLE bug18634s (a int, b int);
+INSERT INTO bug18634s VALUES (1, 2);
+
+MERGE INTO bug18634v t USING bug18634s s ON s.a = t.a
+WHEN MATCHED THEN UPDATE SET b = s.b
+WHEN NOT MATCHED BY SOURCE THEN DELETE;
+
+SELECT * FROM bug18634t;
+
+DROP TABLE bug18634t CASCADE;
+DROP TABLE bug18634s;
+
 -- prepare
 
 RESET SESSION AUTHORIZATION;
