Вопрос по mysql, php – PDOstatement (MySQL): вставка значения 0 в поле бита (1) приводит к 1, записанному в таблице

22

Я использую поле bit (1) для хранения логических значений и записи в таблицу, используя подготовленные операторы PDO.

Это тестовая таблица:

<code>CREATE TABLE IF NOT EXISTS `test` (
  `SomeText` varchar(255) NOT NULL,
  `TestBool` bit(1) NOT NULL DEFAULT b'0'
) ENGINE=MEMORY DEFAULT CHARSET=latin1;
</code>

Это тестовый код:

<code>$pdo = new PDO("connection string etc") ;
$statement = $pdo->prepare('INSERT INTO `test` (SomeText,TestBool) VALUES (?,?)') ;
$statement->execute(array("TEST",0)) ;
</code>

Выполнение этого кода дает мне строку со значением 1 под TestBool. И то же самое, используя bindValue () и bindParm (). Я также попробовал именованные заполнители (вместо?) С тем же результатом.

Тогда я попробовал:

<code>$statement = $pdo->prepare('INSERT INTO `test` (SomeText,TestBool) VALUES ("TEST",0)') ;
$statement->execute() ;
</code>

Который работал правильно (TestBool имеет значение 0). Перфорация в SQL непосредственно в MySQL также работает.

Обратите внимание, что вставка 1 всегда работает.

Так почему бы заполнителям не вставить значение 0? (и как мне на самом деле это сделать?)

Вы уже используете PDO, это хорошо. Почему бы не воспользоваться функцией именованных заполнителей в PDO? Смотрите учебник:phpeveryday.com/articles/… Madara Uchiha♦
Да, вам не нужно помнить порядок ваших переменных. Вы увеличиваете свою абстракцию кода. Madara Uchiha♦
Для целей этого вопроса я попробовал это, и это не имеет никакого значения. Для общего вопроса, есть ли преимущество в использовании, кроме удобства? (Это часть DAL, так что она все равно будет сгенерирована) Peter

Ваш Ответ

4   ответа
1

Вы можете попробовать это без параметра

if($_POST['bool'] == 1)
{
 $bool = "b'1'";
}
else
{
 $bool = "b'0'";
}
$statement = $pdo->prepare("INSERT INTO `test` (SomeText,TestBool) VALUES (?,$bool)") ;
$statement->execute(array("TEST")) ;

и нет проблем с безопасностью

3

Так какprepare добавляет' к вашему параметру, нужно только добавитьb перед именем параметра

$statement = $pdo->prepare('INSERT INTO `test` (SomeText,TestBool) VALUES (?, b?)');
$statement->execute(array("TEST", 1 /* or TRUE */));

Note: ты можешь использовать1, 0  или жеTRUE, FALSE.

28

Столбец BIT представляет собой двоичный тип в mysql (хотя он задокументирован как числовой тип - это не совсем верно), и я советую избегать его из-за проблем с клиентскими библиотеками (что доказывает проблема PDO). Вы избавите себя от многих проблем, если измените тип столбца на TINYINT (1)

TINYINT (1) будет, конечно, потреблять полный байт памяти для каждой строки, но в соответствии с документами mysql BIT (1) будет делать то же самое.

от: http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html

Требуемое хранилище битов: приблизительно (M + 7) / 8 байт, что говорит о том, что столбец BIT (M) также выровнен по байту.

Также я нашел это:https://bugs.php.net/bug.php?id=50757

Таким образом, вы можете проверить, работает ли следующий код так, как вы ожидаете:

$pdo = new PDO("connection string etc") ;
$statement = $pdo->prepare('INSERT INTO `test` (SomeText,TestBool) VALUES (:someText,:testBool)') ;
$statement->bindValue(':someText', "TEST");
$statement->bindValue(':testBool', 0, PDO::PARAM_INT);
$statement->execute();

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

Error: User Rate Limit ExceededPDO::PARAM_INTError: User Rate Limit ExceededPDO::PARAM_INTError: User Rate Limit Exceeded$statement->bindValue(':testBool', (int)$_POST['zero'], PDO::PARAM_INT);Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Peter
5

По умолчанию pdo не использует подготовленные операторы для драйвера mysql, он эмулирует их, создавая динамический sql за кулисами для вас. Sql, отправляемый в mysql, в конечном итоге становится одинарным кавычком 0, подобным «0», который mysql интерпретирует как строку, а не число.

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Это должно сработать сейчас, и вы также будете фактически использовать реально подготовленные заявления.

Error: User Rate Limit Exceeded Peter

Похожие вопросы