Что на самом деле неправильно, так это то, что интервальная арифметика не корректирует дни - см. 6-ую ссылку в ссылке:
Когда интервальные вычисления возвращают значение datetime, результатом должно быть фактическое значение datetime, или база данных возвращает ошибку.
ADD_MONTHS
делает; как эта ссылка говорит:
Если дата является последним днем месяца или если в результирующем месяце меньше дней, чем в компоненте дня, то результатом является последний день результирующего месяца.
Итак, ADD_MONTHS(DATE '2011-12-31', -1)
дает вам 2011-11-30, в то время как DATE '2011-12-31' - INTERVAL '1' MONTH
пытается дать вам 2011-11-31, что, как говорится в сообщении, не является действительной датой.
(Это спорный вопрос, если такое поведение на самом деле не так,. Это неожиданно, но я считаю, что это соответствует требованиям ANSI Там может быть раз вы хотите, чтобы работать так, хотя я не могу думать о какой-то ...)