This is working as designed.
- When you reference a column name in a subquery (Num in your case) SQL firsts looks for that column in the tables in your subquery (#TmpProduct in your case). If it doesn't find that column in the subquery tables it then looks for that column in the outer query (Product in your case). If it finds it there it then uses that column. You will only get an error if that column name is not in the tables of either the inner subquery or outer query. Since Num is in Product you do not get an error. This is the way SQL has always worked.
- Since Num is in Product and not #TmpProduct, SQL uses the Num in Product. So your query effectively becomes UPDATE Product SET Price =0 WHERE Num IN (SELECT Num FROM Product);
And since that is true for every row in Product, Price gets set to zero for every row.
You want to get into the practice of always explicitly specifying the table each column is in (particulary when the query references more than one table). So write your query like
UPDATE Product SET Price =0 WHERE Product.Num IN (SELECT #TmpProduct.Num FROM #TmpProduct);
If you do that, you will be given an error for invalid column name 'Num' and the query will not run.
Tom