Подготовка на PDO - предотвратяване на актуализация на SQL с нулева стойност

Имам незадължителен вход, осигурен като стойност „тип“. Опитвам се да попреча на оператора да актуализира типа, ако е нулеви данни и да продължа да актуализирам стойността на оборудването.

Изкуших се да създам отделни изрази за подготовка, зависещи от PHP проверка на null, но след това открих SQL ISNULL(). Не съм го използвал преди и не съм сигурен как да го използвам в подготовка, освен ако няма по-добър начин за постигане на това?

PHP:

    $update = $db -> prepare("UPDATE room 
    SET type = ISNULL(@:type,:type), equipment = :equipment 
    WHERE room_id = :room_id");

    $update -> bindParam(":room_id", $room_id);
    $update -> bindParam(":type", $data['type']);
    $update -> bindParam(":equipment", $equipmentList);

    $update -> execute();

Получавам „SQLSTATE[42000]: Синтактична грешка или нарушение на достъпа: 1582“ при опит за горното.

АКТУАЛИЗАЦИЯ:

    UPDATE room 
    SET type = IFNULL(:type, type), equipment = :equipment 
    WHERE room_id = :room_id

Добре, този правилен синтаксис коригира грешки, благодарение на eggyal! Проблемът сега е, че null :type стойностите се актуализират и базата данни valuetype(която е enum) не се използва вместо null. Проверих два пъти в php преди SQL, че стойностите :type са null.

Защо IFNULL все още връща нула?


person Orbitall    schedule 21.01.2016    source източник
comment
Възможен дубликат на Актуализиране на полето, когато не е нулево   -  person KhorneHoly    schedule 21.01.2016
comment
Защо просто не проверите в PHP дали е null и ако не - изпълните оператора, иначе не правите нищо? Поддържайте го просто и е просто, ако е проверено в PHP, тъй като изобщо няма да достигне MySQL - следователно е още по-бързо.   -  person Mjh    schedule 21.01.2016


Отговори (3)


  • Използвайте bindValue вместо bindParam, вие не променяте стойността на параметъра, следователно не е необходимо да го предавате по препратка.

  • ако типът данни в MySQL може да съдържа null, тогава можете да му кажете, че изпращате стойност NULL. Код:

$update -> bindValue(":type", $data['type'], is_null($data['type'] ? PDO::PARAM_NULL : PDO::PARAM_STR);

Ако вашата целева колона не може да съдържа null, тогава изобщо не е необходимо да изпълнявате заявката.

person Mjh    schedule 21.01.2016

Функцията ISNULL() на MySQL приема само един аргумент и връща 1 или 0, което показва дали този аргумент е нулев или не, съответно. Той е еквивалентен на оператора за сравнение IS NULL.

MySQL има функция с 2 аргумента IFNULL(), която може би е било това, което сте възнамерявали да използвате (въпреки че аргументите, които сте приложили, са глупости)?

UPDATE room 
SET    type      = IFNULL(:type, type),
       equipment = :equipment 
WHERE  room_id   = :room_id

Ако :type не е NULL, ще се използва неговата стойност; в противен случай вместо това ще се използва съществуващата стойност на колоната type (без промяна).

person eggyal    schedule 21.01.2016
comment
Все още може да е важно полето оборудване да бъде актуализирано. - person trincot; 21.01.2016
comment
Разбирам..обърках ги, благодаря ви за обяснението, помогна много! Той е без грешки, но сега изключва нулеви стойности. Стойността на типа, съхранена в базата данни, е „enum“, ще повлияе ли това по някакъв начин на резултата? - person Orbitall; 21.01.2016
comment
@Orbitall: Съжалявам, не разбирам какво имате предвид под освен нулеви стойности сега—моля, разяснете? - person eggyal; 21.01.2016
comment
@Orbitall - защо проверяваш за NULL в заявката? Очевидно не искате NULL под никаква форма или начин, вашият тип данни очевидно дори няма да го приеме. Защо си правите труда да правите тази проверка в SQL? Това е тривиално в php if(empty($your_variable)) return false; и работата е свършена, работата на SQL не е да прилага валидиране на вашия вход. - person Mjh; 21.01.2016
comment
@eggyal: IFNULL() изглежда не работи по предназначение. Нулевата стойност ':type' се използва и не се заменя с текущата стойност на базата данни 'type'...Проверете актуализацията. - person Orbitall; 21.01.2016
comment
@Mjh: Е, моят първоначален въпрос беше зададен ... освен ако няма по-добър начин за постигане на това?. Опитвам първия отговор на моя въпрос, като приемам, че това е най-добрият метод. Предполагате ли, че трябва да имам множество SQL изрази, зависещи от нулев вход? Това ще бъде ли много по-ефективно? - person Orbitall; 21.01.2016

Можете да използвате функцията COALESCE(). Той взема толкова аргументи, колкото му дадете, и връща първия ненулев аргумент, който среща, ако има такъв. В противен случай връща NULL.

UPDATE room 
SET type = COALESCE(:type, type), equipment = :equipment 
WHERE room_id = :room_id
person coladict    schedule 21.01.2016