Он отлично работает оракул
merge into table1 t1
using (select * from table2) t2
on (t1.empid = t2.empid)
when matched then update set t1.salary = t2.salary
В ответе Финка правильно описана ваша основная проблема, которая заключается в том, что ваш первый цикл добавляет несколько ссылок на один и тот же экземпляр 'clsMatch' в вашу коллекцию. Я просто расскажу подробнее, почему ваше исправление работает.
В VBA строка типа:
Dim c As New Collection
на самом деле не создает новую коллекцию. Оператор 'Dim' всегда является просто объявлением. Думайте о форме 'As New' как о сокращении для этого:
Dim c As Collection
'...
'(later, when you're about to use 'c')
If c Is Nothing Then
Set c = New Collection
End If
'...
Вот почему уничтожение вашей ссылки путем установки содержащей ее переменной в 'Nothing' сработало. [ПРИМЕЧАНИЕ: тому, кто отредактировал этот вопрос, чтобы сказать "не работал" - это меняет смысл ответа и делает его неправильным. Пожалуйста, прочитайте исходный вопрос. ОП обнаружил, что установка переменной в "Nothing" сработала, а я объяснял почему это так]. Когда цикл возвращался к строке 'oMatch.setLineNumber', VBA "услужливо" создавал новый экземпляр 'clsMatch' для вашей переменной 'oMatch', на которую она должна была ссылаться, и тогда вы получали несколько различных экземпляров в вашей коллекции.
Возможно, было бы лучше сделать это явно:
Dim oMatch As clsMatch
For i = 0 To 10
Set oMatch = New clsMatch
oMatch.setLineNumber i
oCollection.Add oMatch
Next
Обратите внимание, что (в отличие от C/C++ или ?NET) не имеет значения, где находится объявление 'Dim'. Оно не "выполняется" несколько раз внутри цикла, и область применения того, что оно объявляет, является процедурной, даже если оно появляется внутри цикла.
Когда вы добавляете объект oMatch в коллекцию, он передает переменную по ссылке на память. Когда вы снова объявляете oMatch как новый clsMatch, он не уничтожает указатель локальной памяти первого объекта, который вы создали. Он просто отдает вам ту же локальную область памяти, что и первый объект oMatch, который вы создали, даже если вы объявили его как новый объект. VBA использует ByRef в качестве техники передачи памяти по умолчанию. Затем места памяти коллекции обновляются, оба указывают на одно и то же место памяти с обновленным номером строки. Таким образом, все указатели памяти коллекции будут указывать на один и тот же последний созданный вами объект.
Когда вы устанавливаете oMatch = nothing, то сбрасывается указатель локальной памяти, создается новый объект oMatch с новым указателем локальной памяти, и все указатели коллекции будут указывать на свои правильные объекты.
По умолчанию в VBA передача памяти осуществляется по ByRef, в отличие от VB, где по умолчанию используется ByVal, поэтому вы можете столкнуться с этой оговоркой время от времени.