Dele Alli starred with a brace for Tottenham with Christian Eriksen also scoring before Cristiano Ronaldo's late consolation last night.
The result ensured that Mauricio Pochettino's side are through from Group H with two games to spare, while Real will have to wait to join them.
"We don't want to just compete with these teams -- we want to beat them. I'm happy to get two goals, but more importantly it was a win," Alli told BT Sport.
Alli netted again on 56 minutes when his shot beat Kiko Casilla with the aid of a deflection off Sergio Ramos.
Also Read
Eriksen made it 3-0 at the end of a counter-attack on 65 minutes, before Real reduced the deficit late on as Ronaldo scored his sixth goal in the competition this season.
This was Real's first group-stage defeat in five years and, following a shock La Liga loss at Girona at the weekend, the pressure is building on coach Zinedine Zidane.
Raphael Guerreiro gave Dortmund a first-half lead but they are still looking for a win in Europe this season after Mickael Pote levelled for APOEL on 51 minutes.
Manchester City continued their sensational form as they saw off Napoli 4-2 in Italy to make it four wins from four in Group F and advance to the knockout phase for the fifth season running.
Lorenzo Insigne put the Serie A leaders in front, but Nicolas Otamendi headed City level and his fellow centre-back John Stones then scored with a header that went in off the underside of the bar.
Aguero's strike allowed him to become City's all-time leading scorer on 178 goals, passing the old mark of 177 set by Eric Brook in the 1930s.
"What he has achieved has made him a legend, he's gone down in history, so I would tell him to enjoy," said City coach Pep Guardiola of Aguero, the former son-in-law of Argentina and Napoli great Diego Maradona.
Shakhtar Donetsk need just a draw in Naples in three weeks to go through too after beating Feyenoord 3-1.
Marlos, the Brazil-born Ukraine international, then scored twice to secure the victory as Feyenoord are eliminated.
Meanwhile Liverpool moved clear at the top of Group E with a comfortable 3-0 win over Maribor at Anfield.
There would be no repeat of their 7-0 romp in the reverse fixture in Slovenia as the Reds had to wait until the 49th minute for Mohamed Salah to give them the lead.
James Milner then saw his penalty tipped onto the post but he set up Emre Can to double Liverpool's lead before substitute Daniel Sturridge completed the scoring.
Earlier, Besiktas missed a chance to secure their place in the last 16 as they drew 1-1 with Monaco in Istanbul, Cenk Tosun's penalty cancelling out the opener from Rony Lopes.
The Turkish champions would have been through with a win but will now hope for a draw at home to second-placed Porto to qualify next time out.
Porto beat RB Leipzig 3-1 in Portugal, with Hector Herrera, Danilo Pereira and Maxi Pereira scoring their goals as Timo Werner replied for the Germans.
Disclaimer: No Business Standard Journalist was involved in creation of this content