I need to decrement a value with an atomic database operation, is it possible using Magento models?

setNumber($number) works like number = $number, but I need it to be decremented in SQL query.

Is it possible in Magento or do I have to write the SQL query myself?

  • 4
    I'm voting to close this question as off-topic because it is about MYSQL – Sander Mangel Feb 17 '15 at 13:55
  • 2
    @Sander-MageStackDay2015 It's not about MYSQL, I am asking if there is a Magento function that instead of setNumber(number) has something like decreaseBy(number) – tmm Feb 17 '15 at 13:58

Yes, it's possible, using Zend_Db_Expr:

$object->setNumber(new Zend_Db_Expr('number-1'));

For reference:

The method Mage_Core_Model_Resource_Abstract::_prepareDataForSave() contains the following code:

if ($object->hasData($field)) {
    $fieldValue = $object->getData($field);
    if ($fieldValue instanceof Zend_Db_Expr) {
        $data[$field] = $fieldValue;
    } else {
        ... [normal value processing follows]

EAV Models:

Note that you only can reference the attribute by its name ("number" in the example) if it's a real column of the main table, not an EAV attribute.

Although the abovementioned method is only used by models with flat tables, Zend_Db_Expr can be used for EAV attributes as well, the method that handles it is Varien_Db_Adapter_Pdo_Mysql::prepareColumnValue().

BUT you always have use the column name "value":

$product->setNumber(new Zend_Db_Expr('value-1'));

You don't need to specify a table alias because during save each attribute gets processed with its own query, so "value" is not ambiguous.

  • /me sheds a tear... – benmarks Feb 17 '15 at 15:28
  • 1
    They are tears of joy. Great answer. – benmarks Feb 17 '15 at 15:56
  • And how does one do this with a collection? :) – philwinkle Feb 17 '15 at 20:24
  • There is no direct way to save attributes in a collection at once but you probably can do some clever stuff with $collection->getSelect() – Fabian Schmengler Feb 17 '15 at 20:45
try ->setNumber(getNumber() - $number)

Edit: This would be equivalent of Set number = number - X in mysql where X is $number.

If you want to do it in MySQL only then you just need to write a query.

  • this will be number=some_number in sql query – tmm Feb 17 '15 at 14:01
  • write a sample query you want or an example...you aren't clear enough. – Paras Sood Feb 17 '15 at 14:03
  • UPDATE table SET number = number - 1 – tmm Feb 17 '15 at 14:06
  • See my updated answer..... – Paras Sood Feb 17 '15 at 14:07
  • 1
    Technically, it's not because you can get race conditions. – Fabian Schmengler Feb 17 '15 at 14:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.