View previous topic :: View next topic |
Author |
Message |
Den_CarpeTerra
Joined: 11 Feb 2005 Posts: 9
|
Posted: Wed Mar 02, 2005 20:50 Post subject: GetLastAutoID function added to aps_inc |
|
|
I had need for this function and thought others might need it as well. Perhaps add it to the NWNX distribution?
Code: | //NEW: gets the last auto increment number assigned to field
int GetLastAutoID(string sTable, string sField);
int GetLastAutoID(string sTable, string sField) {
int id = 0;
string SQL = "SELECT "+sField+" FROM "+sTable+" WHERE "+sField+" IS NULL";
SQLExecDirect(SQL);
if (SQLFetch()) id = StringToInt(SQLGetData(1));
return id;
}
|
|
|
Back to top |
|
|
dguntner
Joined: 31 Dec 2004 Posts: 116
|
Posted: Thu Mar 03, 2005 6:56 Post subject: |
|
|
What exactly is an AutoID that you're getting the last one of?
--Dave
Last edited by dguntner on Fri Mar 04, 2005 9:20; edited 1 time in total |
|
Back to top |
|
|
Den_CarpeTerra
Joined: 11 Feb 2005 Posts: 9
|
Posted: Thu Mar 03, 2005 8:36 Post subject: |
|
|
When you set up a table, sometimes you want to have an index field which is set to auto-increment. Then when you add a record, you might need to grab this index field back and do something with it. That's what this function does, determine the last index number assigned.
There are other, more direct, ways of going about this depending on what version of mySQL you are running, but this works 100% of the time. |
|
Back to top |
|
|
NoMercy
Joined: 03 Jan 2005 Posts: 123 Location: UK
|
Posted: Thu Mar 03, 2005 12:34 Post subject: |
|
|
I don't fully understand it, what would you give in sField, the field which is the auto-incremented number? |
|
Back to top |
|
|
Manuel
Joined: 30 Dec 2004 Posts: 51
|
Posted: Thu Mar 03, 2005 17:56 Post subject: |
|
|
Yeah, this script is a bit confusing. The sField couldn't be the autoincrement field since it would have been populated. Where is the NULL value being queried for? A better approach might be to do a:
Code: | string SQL = "SELECT MAX("+sField+") FROM "+sTable; |
The majority of databases (MySQL, Oracle, SQL Sever) respect the MAX function but it is not 100% gauranteed to return the correct insert unless you put it in a transaction.
For database specific incrementing techniques:
MySQL and SQLite use AUTO_INCREMENT and AUTOINCREMENT respectively.
Oracle and PostgreSQL use SEQUENCE and TRIGGER that performs the assignment to id columns.
SQL Server uses IDENTITY. _________________ I only know enough to be dangerous. |
|
Back to top |
|
|
Den_CarpeTerra
Joined: 11 Feb 2005 Posts: 9
|
Posted: Thu Mar 03, 2005 19:49 Post subject: |
|
|
The sField is the auto-increment field, so if your table looks like this:
CREATE TABLE `my_table` (
`serialID` int(10) unsigned NOT NULL auto_ '0',
`name` varchar(32) NOT NULL default '',
`item` blob NOT NULL,
PRIMARY KEY (`serialID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Then you would use in your script:
int serialID = GetLastAutoID("my_table", "serialID");
>The sField couldn't be the autoincrement field since it would have been populated.
Your suggestion to use MAX, while it also works, requires a lot more database work than is needed. And just because you don't understand it doesn't mean it won't work. |
|
Back to top |
|
|
Den_CarpeTerra
Joined: 11 Feb 2005 Posts: 9
|
Posted: Thu Mar 03, 2005 22:37 Post subject: |
|
|
I should also say that I tried to use the last_insert_id() to return the auto-increment id as it is assigned, but couldn't get it to work with NWNX. This would be the best and most direct way to get this information, but failing that, the solution I posted above works. |
|
Back to top |
|
|
Kosmous
Joined: 10 Jan 2005 Posts: 44
|
Posted: Fri Mar 04, 2005 6:33 Post subject: |
|
|
you lost me there with this SQL statement:
string SQL = "SELECT "+sField+" FROM "+sTable+" WHERE "+sField+" IS NULL";
why would using the where statement: "WHERE Fieldname IS NULL" retrieve the last inserted auto-incremented row? Ive had your problem and i know why last_insert_id doesnt work (since it only works if you DONT end your current session with mysql between inserting the last row and querying its ID). However, i dont quite understand how this query obtains the last inserted id.
What ive used is pretty simple (dunno if its efficient) and works pretty well: "Select " +sField+ " From " +sTable+ " ORDER BY " +sField+ " DESC LIMIT 1"
probably not the best way to do it but its pretty easy to see how this works. It simply orders the rows by sField in reverse (last to first) then limits the number of rows taken to 1. Since mysql always adds + 1 to the last/highest id (even if the last id was previously deleted) even if there are skipped index numbers when using auto-increment, this should always work perfectly (unless another id was inserted between ur last insert statement and the select query). |
|
Back to top |
|
|
JeroenB
Joined: 31 Dec 2004 Posts: 228 Location: Netherlands
|
Posted: Fri Mar 04, 2005 14:03 Post subject: |
|
|
If you have a field in a table that is auto-increasing, lets name it id, then I would use the following query to fetch the latest id:
Code: | SELECT max(ID) FROM table |
This query will return you one row with only one field with the latest incremented id value, hence the function max returns the highest number in the rows. |
|
Back to top |
|
|
Manuel
Joined: 30 Dec 2004 Posts: 51
|
Posted: Fri Mar 04, 2005 17:19 Post subject: |
|
|
I'd have to test your SQL statement myself but even if it works, I wouldn't use it. The reason why I say it's confusing (not that it wouldn't work) is because I DO understand it. My understanding is that if you do an INSERT, the auto-increment field gets (wait for it) ... incremented. Therefore a value should exist in that column. The schema definition itself calls for NOT NULL on that column. Doing a SELECT on that column WHERE the value IS NULL should return no results. If this isn't the case, then I'd consider it a bug.
Doing a SELECT MAX will not cause much overhead in the case where the ID field is an INDEX or KEY as you have wisely done. _________________ I only know enough to be dangerous. |
|
Back to top |
|
|
JeroenB
Joined: 31 Dec 2004 Posts: 228 Location: Netherlands
|
Posted: Sat Mar 05, 2005 10:52 Post subject: |
|
|
An auto-increment field is never empty, as it must be created as a key item (not null). The RDBMS will always insert an unique value in the field, only in special cases an id will be reused (when it is not used in the db anymore, but this is rarely the case.
http://dev.mysql.com/doc/mysql/en/example-auto-increment.html |
|
Back to top |
|
|
Grinning Fool
Joined: 12 Feb 2005 Posts: 264
|
Posted: Wed Mar 09, 2005 9:06 Post subject: |
|
|
For mysql: select LAST_INSERT_ID() |
|
Back to top |
|
|
Gryphyn
Joined: 20 Jan 2005 Posts: 431
|
Posted: Tue May 17, 2005 0:15 Post subject: |
|
|
Sorry to rain on everyones parade, but all these ONLY work if you can guarantee the order that each row iss inserted into the table, and the order of each check for the 'LastID'. Since each NWNX call is it's own transaction, this is not possible.
It's possible that, say, two/three (or more) inserts occur prior to NWNX processing the 'Last ID' retrieval.
The only way to make sure you get the ID assigned to your insert is to have a secondary unique field (with an Index for performance)
CREATE TABLE my_table (
serialID int(10) unsigned NOT NULL auto_increment,
name varchar(32) NOT NULL default '',
data <text|blob> default NULL,
PRIMARY KEY (serialID)
UNIQUE (name)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO my_table SET name = '<value>';
SELECT SerialID FROM my_table WHERE name = '<value>';
This ensures that you get the SerialID related to `<value>`, not just the last row entered.
As to actually getting the LastID Kosmous had the right of it
SELECT SerialID FROM my_table ORDER BY SerialID DESC LIMIT 1;
which also lets you find the NEXT SerialID to be added...
SELECT SerialID+1 FROM my_table ORDER BY SerialID DESC LIMIT 1;
Cheers
Gryphyn
[Ed.] Redirected back here. (so an update)
Things have changed a little with NWNX4.
You can now execute multiple sql statements. This means that
SELECT LAST_INSERT_ID() can be part of the same transaction and WILL return the value that you expect if it's part of the same SQLExecDirect() statement as the insert (eg "INSERT stuff; SELECT LAST_INSERT_ID()") |
|
Back to top |
|
|
|