Потому что во втором случае ты занимаешься ерундой.
Причем дважды
Раз уж ты используешь именованные плейсхолдеры, то зачем их привязывать по одному? Ну ведь они специально сделаны для того, чтобы просто передать ассоциативный массив в execute()!
Тем более, что у тебя совершенно правильная идея отфильтровать ненужное из массива $_POST. Ну так вот сначала отфильтруй, а потом тупо передавай на исполнение, без всяких циклов. Только способ фильтрации у тебя неправильный. Надо не лишнее выкидывать, а нужное контролировать.
Всегда может возникнуть такая ситуация, когда пользователь не имеет права изменять ту или иную колонку в таблице. Поэтому-то и надо всегда четко указывать, какие конкретно поля ты хочешь обновить- ведь из браузера к тебе может придти любой набор полей.
$in = ['bText','type','bId'];
$data = array_intersect_key($_POST, array_flip($in));
$sql = "UPDATE `$dbname` SET `bText`=:bText WHERE `type`=:type AND `bId`=:bId";
$stm = $pdo->prepare($sql);
$stm->execute($data);
А так-то да, Денормализатор правильно написал. Я же тебе давал ссылку, в которой написано, что
bindValue() всегда следует предпочесть bindParam(). Там же написано, что ни ту ни другую использовать не нужно.