Сколько же записей обновилось?

Вроде бы простой вопрос, сколько рядов было затронуто SQL-операцией UPDATE, но и здесь притаился подводный камень (о котором, правда честно предупреждают в документации). В MySQL в это число могут не попадать записи, у которых данные не потребовалось изменять. А значит, если REPLACE не подходит, то нужно проводить дополнительные проверки на тему того, сколько же данных вы обновили. Я споткнулся об этом в функции mysql_affected_rows в PHP. Там-же можно найти один из вариантов решения – использовать mysql_info, но в этом случае нужно парсить строку с ответом. Ну а дальше в вариантах SELECT‘ы и т.п.

SQLite и JOIN

Обычно по работе, когда требуется сохранить какую-то информацию (вроде справочников абонентов) в компоненте, которая отвязана от основного проекта, я стараюсь использовать BerkleyDB. Она быстра, когда для доступа используется только какой-то ключ и вполне практична. Но в одном из проектов с ростом количества доступов к файлу базы от разных потоков стали происходить коллизии и терялись части данных (частично виню в этом механизм доступа, реализованный в PHP, частично – недоработки в компоненте). К тому же усложнялась структура данных, хранящихся в каждом ключе. Для разрешения вопроса был выбран SQLite, т.к. с ним возможно разрисовать структуру данных, и поддерживается одновременная работа с одной базой.

В ходе проверок запросов выяснился весьма интересный момент. В привычных мне ранее PostgreSQL или MySQL конструкция вида:

SELECT b.id, f.title as foo_title, b.title
FROM bar b LEFT JOIN foo f ON f.id=b.foo_id

будет отрабатывать вполне успешно. Но не в SQLite. И дело не только в том, что конструкцию с JOIN надо заключать в круглые скобки. Внутренняя логика SQLite превращает это выражение в один источник и не позволяет выделить из какой именно таблицы тебе нужно взять поле. И в данном примере значение title из foo перекроет значение title из bar. Т.е. результатом запроса вида:

SELECT id, title
FROM (bar b LEFT JOIN foo f ON f.id=b.foo_id)

Будут значения id и title из таблицы foo. Выход один: делать объединение таблиц в конструкции WHERE, тем более, как говорит документация потери быстродействия в этом случае не будет.