Dec 03

Предыстория такова: писал я скрипт, который коннектится к pop3-серверу, выдирает оттуда все аттачи с нужными названиями файлов, парсит эти файлы и заносит отпарсенные данные в бд. Все было отлично, пока я писал на линуксе (писал, естественно, на php + mysql), а вот при попытке запустить этот скрипт на свежеустановленной винде (естественно, с апачем и прочим барахлом) - пошли error’ы…

Сразу скажу - пост написан совсем не для того, чтобы учить меня юзать ORM и ActiveRecord. Всё мы знаем, всё умеем, ноэто не тот случай.

Начнем издалека, а именно с PHP. В нем есть такой хороший и нужный (кроме программеров на си) тип как boolean, у которого есть значения true и false. Все бы хорошо, но есть одна проблема - при работе с бд все значения нужно преобразовывать к типу string (ну, а как вы sql писать собираетесь)… Точнее, это не проблема, а такой факт… Проблемы начинают возникать, когда мы преобразовываем boolean -> string. Преобразование получается довольно хитрое, в результате которого мы вместо true получаем ‘1′, а вместо false - … нет, если бы мы ‘0′ получали - все было бы отлично… мы получаем ”, т.е. пустую строку.

Этой проблеме уже хер знает сколько лет. Лечить ее разработчикам, видимо, влом.

Естественно, при вставке в БД все значения квотятся. Т.е. если у нас был запрос, в котором значение для поля будет false - получим примерно следующее:

INSERT INTO table(column) VALUES('')

Если бы типом column была строка - было бы всё ок. Но у меня это было булевое поле (если быть точным - smallint(1), т.к. в MySQL нет типа Boolean). И вот в линуксе (ubuntu) на MySQL Server’е из стандартных репозиториев все работало замечательно. А в винде - начало ругаться на эту строку.

Естественно, в данном случае можно решить проблему храня в переменных PHP не true/false, а 1/0, но меня заинтересовало - а почему же на Linux’е все это дело работает.

Покопавшись в настройках сначала PHP, а потом и MySQL (после того, как в PHP’шных настроках ничего интересного не нашел) - в my.ini (конфигурационный файл MySQL) были найдены интересные строчки:

# Set the SQL mode to strict
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

После того, как я их закомментировал, все заработало нормально, но…

Подытожу - при работе с MySQL в PHP не используйте переменные типа boolean, пользуйтесь int’ами. Даже если у вас все работает с true/false - не факт, что оно заработает у вашего заказчика.

written by fxposter \\ tags: ,


23 Responses to “Boolean в MySQL и PHP”

  1. 1. JackYF Says:

    (кроме программеров на си)
    Дезинформация. Начиная с c99, у сишников есть bool. На дворе скоро 2008. Исправляйся.

  2. 2. Sam Says:

    Тоже всегда юзал bool :)

  3. 3. FX Poster Says:

    JackYF
    Буду знать, спс.

    Sam
    Ну вот теперь я задумываюсь периодически – что лучше юзать – bool или int. %)

  4. 4. Yuriy Says:

    это не баг, нужно преобразовывать к int

  5. 5. FX Poster Says:

    Ну допустим. Покажи мне тогда логику:
    true: boolean -> int -> string
    false: boolean -> string (причем непонятно каким образом)

  6. 6. Yuriy Says:

    Начнем с того, что в MySQL есть тип BOOL, BOOLEAN, который является синонимом для TINYINT(1).
    Поэтому преобразований к строке не будет. Запрос будет выглядеть следующим образом:
    $sql = “INSERT INTO table(column) VALUES(‘” . (int)$variable . “‘)”;
    Или я что-то не так понял?

  7. 7. FX Poster Says:

    $sql = “INSERT INTO table(column) VALUES(’” . (int)$variable . “‘)”;

    Это уже преобразование к строке. Сначала к int’у, потом к строке. ;)

  8. 8. Yuriy Says:

    Ага, точно :)
    Но, ведь для типа string, false – это пустая строка и “0”. Поэтому очень даже логично преобразовывать к int.

  9. 9. FX Poster Says:

    Да мне много чем PHP не нравится. В частности, нестрогой типизацией. ;) Ну вот не нравится мне такое поведение с bool’ами…

  10. 10. larin Says:

    @FX Poster,
    а чем не нравится?
    В чем проблема сделать как посоветовали: $sql = “INSERT INTO table(column) VALUES(’” . (int)$variable . “‘)”; ?

    А из-за не строгой типизации PHP многие вещи программистам “прощает” и упрощает во многих случаях работу.

  11. 11. FX Poster Says:

    А из-за не строгой типизации PHP многие вещи программистам “прощает” и упрощает во многих случаях работу.
    Тут спорить просто не хочется. Лично я упрощений не вижу. Вижу, скажем так, не совсем логичные преобразования в очень “удачных” моментах скриптов.

    Преобразовывать – я то могу, мне не сложно. Но вот такие проблемы мне не нравятся. Очень напоминает проблемы верстки:
    – “А в IE6 оно неправильно показывается :(”
    – “А ты height: 1%; поставь ;)”

  12. 12. larin Says:

    Да, спорить не будем. Но сравнение с IE не очень удачное. Это из другой оперы.

  13. 13. Bolk Says:

    Что-то я сейчас попробовал в MySQL под Виндами вставить ” в поле BOOL, всё прокатило. MySQL сделал вполне логичное преобразование ” -> 0 (ведь MySQL — тоже язык с нестрогой типизацией) http://dev.mysql.com/doc/refman/5.0/en/type-conversion.html

    В преобразовании false -> ” не вижу ничего страшного и нелогичного.

  14. 14. FX Poster Says:

    По умолчанию в MySQL под виндой в настройках предлагается использовать строгий режим, который, ” за bool не воспринимает. :(

  15. 15. FX Poster Says:

    Bolk
    Да, кстати, что с твоим сайтом?

  16. 16. Bolk Says:

    DDoS на сайт Экслера. Вот и мой лежит, попал под замес.

  17. 17. Bolk Says:

    Если бы типизация была строгая, то и ‘0’ не превращалась бы в 0. Так как это преобразование varchar и int.

  18. 18. FX Poster Says:

    Если бы типизация была строгая, то и ‘0′ не превращалась бы в 0. Так как это преобразование varchar и int.
    Да ладно, хер с ним :)

  19. 19. adw0rd Says:

    Да мне много чем PHP не нравится. В частности, нестрогой типизацией. ;) Ну вот не нравится мне такое поведение с bool’ами…

    А вы строго типизируйте сами :)

  20. 20. FX Poster Says:

    1. Лучше на “ты”.
    2. Да бред, блин. Вон, Юрец пишет о том же…

  21. 21. adw0rd Says:

    Прочел статью Юрца, согласен бред :)
    Хотя anycolor правильно заметил что для этого есть “===”… Но все равно бредово

  22. 22. Zeke Fast Says:

    Используйте bindParam из PDO с указанием типа, и проблема отпадёт. А в PHP проблемы возникают не из-за не строгой типизации, а из-за непродуманного механизма автоприведений типа. В руби с этим делом логичней как мне кажется.

  23. 23. FX Poster Says:

    В руби строгая типизация. :)

    PS. А если я не PDO использовал?

Leave a Reply