There's now a module to do this, Serial Field, I recommend you to use that one instead of this option

This snippet will create an auto increment field. You could use this if you have a content type where you need to register a transaction number and you don't want to let the users add the transaction number because you might lose the sequence.

if (!empty($node_field[0]['value'])) {  // the node is not new
  return $node_field[0]['value'];
}
else {  // the node is new
  $count = db_result(db_query("SELECT COUNT(*) from {node} WHERE type = 'transaction'"));
  $node_field[0]['value'] = $count;
}

In this case the Content Type is 'Transaction' so you'll have to change that to the content type you want to count...

Comments

MartysMind’s picture

Unfortunately this method is NOT ATOMIC. If your server is under heavy load it is quite likely that you will end up with nodes with the same id.

If you require a unique ID you should either:

1. Lock the table when you perform the above operation, or;
2. Add an auto increment or;
3. Base it off of the nid (which is atomic).

-Marty

dejamuse’s picture

Not being a programmer, can you explain how to do numbers 1 and 2, and which is the preferred method?

I presume by autoincrement you mean in MySQL as shown here:

http://www.plus2net.com/sql_tutorial/mysql_auto_increment.php

And discussed here:

http://forums.whirlpool.net.au/forum-replies-archive.cfm/513273.html

More discussion on this to further confuse me:

http://th.php.net/mysql-insert-id

Seems to be a lot of controversy about this with respect to the true uniqueness of the ID, which I don't quite understand.

Thanks, Jeff

kentr’s picture

The preferred method really depends on your specific needs (the specifications for the project).

If you can define a "transaction" (or "item", "record", "node", etc) as a content type and all you need is a unique (or unique and increasing) value for each, just use the node id rather than a computed field. A unique, auto-incremented id is internally created for each node.

As mentioned in one of your links, a drawback is that if you create a "transaction" then delete it, the next one will have another new value, so your list of transaction numbers will skip a value. But I'll go out on a limb and generalize that this is preferred in the majority of record-keeping scenarios (intentionally not recycling ID numbers). If you were testing and running up the numbers, it would be possible with a little extra work inside the database to reset the whole thing once you finish the testing.

Someone else will have to comment on how to effectively use table locking for this case, or whether or not it's even possible.

lelizondo’s picture

just use the node id rather than a computed field

The problem with using the nid is that the nid increase when every node is created. Sometimes you don't want that, you want a unique number who increases for only one content type. Take this example, an invoice, each one has a unique number and you have a sequential number that you have to respect, using the nid it's not an option, if you create the node invoice 1 and then you create some other node and then you create the node invoice 2 you'll have that invoice 2 will have nid = 3. not good.

as for deleting the transaction and skipping the old value I just didn't think of that at the moment I created this snippet but it's a good point.

Luis

Parkes Design’s picture

I'm surprised there isn't a product code / serial number / autonumber CCK module floating around. I've been looking but haven't been able to find one yet.

Alauddin’s picture

I think a combination of this module plus the unique_field will do the trick.
http://drupal.org/project/unique_field

druplicate’s picture

This new one is supposed to be truly atomic, just like NID.

http://drupal.org/project/serial

Parkes Design’s picture

Great find, I'm excited to try this one out!

druplicate’s picture

Haven't tried using the serial module yet to insert the serial ID in the node title using the nodeautotitle module. I have a feeling it's the same problem as using NID for this as extensively discussed here:

http://drupal.org/node/194197

vicentefoxxx’s picture

I would like to know if somebody knows how to add a sufix to the Script. For me is working better for translated pages because I want to habe the same number for the original and the translated, that is why is better as the Serial field option.

But I don´t know how to write the sufix :)

Anybody knows it?

Regards and thanks!

theamoeba’s picture

this worked nicely for me:

if (empty($node_field[0]['value'])) {
$count = db_result(db_query("select max(field_client_number_value) from {content_type_customer}"));
$count++;
$node_field[0]['value'] = $count;
}

Anonymous’s picture

You haven't resolved the race condition - which occurs when this code is executed for a different record after yours has started and before your field value has changed. That will result in duplicated values.

chrisjlock’s picture

Found this post after adding my own auto_increment field, but I have the same race issue. For my purpose it really doesn't matter as I'm mostly using this field to track old ids from a db import, but I would like to solve the issue. How would I release the a lock on node save, or would it be better to force a node save just after setting the value release the lock and then letting the node add/edit form save it a second time when its ready?

My code:

if (empty($entity->field_id[$entity->language][0]['value'])) {
    $bundle = $entity->type;
    $result = db_query("SELECT MAX(id.field_id_value) FROM {field_data_field_id} id WHERE id.bundle = :bundle", array(':bundle' => $bundle))->fetchField();
     $entity_field[0]['value'] = $result + 1;
}
j4’s picture

Hi,

Did you find a solution? I need the auto incremental field for my profile type and would greatly appreciate any help.

Thanks
Jaya

Jaya

ah0’s picture

+1
any help please