View previous topic :: View next topic |
Author |
Message |
Disco
Joined: 06 Dec 2006 Posts: 152
|
Posted: Wed Dec 06, 2006 14:17 Post subject: Combined query in MySQL and more |
|
|
Hey folks!
I'd like to do this:
* PC enters module, and I check if he is assigned a database ID (stored on an item called Journal)
* If not I make a new record, collect the ID and store it on the PC's Journal and save his character.
* If I find the ID I update the record with some data
I am used to work with MySQL from PHP and in that case I'd simply fetch the last insert ID with another query (well, there's a dedicated funstion, but nvm that), but I am not sure how trustworthy this is in NWN(X). I'd also prefer to keep the number of database queries to the absolute minimum.
Thanks!
My question: what's the most reliable & efficent way of implementing this? |
|
Back to top |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Wed Dec 06, 2006 16:26 Post subject: |
|
|
If you do this is in a transaction, I'd say the result can be trusted. If not... well, other servers could insert data in the meantime. The probability is low, but not zero.
Do you really need the ID ? Maybe you could get rid of it entirely. If not, you could fetch the newly made entry using Playername + Pcname, which should be unique in that table. You could use that to safely identify the record that was just inserted. _________________ Papillon |
|
Back to top |
|
|
Disco
Joined: 06 Dec 2006 Posts: 152
|
Posted: Wed Dec 06, 2006 16:41 Post subject: |
|
|
I was thinking of using the loginname + timestamp, but a simple ID is quite elegant. It's all about efficiency, and transferring large amounts of INT(6) s is a bit cheaper than strings of 30/40 characters. I need to retrieve the ID only once, and I need to use it very often afterwards for INSERTS and UPDATES. |
|
Back to top |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Fri Dec 08, 2006 12:25 Post subject: |
|
|
The difference is negligible. _________________ Papillon |
|
Back to top |
|
|
Grinning Fool
Joined: 12 Feb 2005 Posts: 264
|
Posted: Fri Dec 08, 2006 16:25 Post subject: |
|
|
Disco wrote: | I was thinking of using the loginname + timestamp, but a simple ID is quite elegant. It's all about efficiency, and transferring large amounts of INT(6) s is a bit cheaper than strings of 30/40 characters. I need to retrieve the ID only once, and I need to use it very often afterwards for INSERTS and UPDATES. |
I have used SELECT last_insert_id() for this via NWNX, and it has worked without issues.
Edit: My bad. I've used it in NWNX4; I haven't tested under NWNX2.
edit again: Nevermind the previous edit -- I just found some old code in NWN1 bug reporting system that shows I /was/ using select last_insert_id() without issues under NWNX2. _________________ Khalidine, a NWN2 persistent world
Looking for volunteers.
Last edited by Grinning Fool on Tue Dec 12, 2006 18:35; edited 1 time in total |
|
Back to top |
|
|
Disco
Joined: 06 Dec 2006 Posts: 152
|
Posted: Tue Dec 12, 2006 15:32 Post subject: |
|
|
Testing it now.
I tried the timestamp + login way, which worked rather well, but the fact that some people use account of 60+ characters gives me the creeps. It's simply not esthetical!
So, stubborn as I am I rewrote the entire script again and used the "INSERT record first and SELECT it on the next transition for the right ID" method. It's also a good way to check if a record has been made anway, as people manage to login before the database scripts are initialised.
No I have another multiple statement question:
I have a record ID and two tables that I want to search two table with this ID. I just want to know if both have an entry. I need to search both tables on more values that just the ID, and I want the result set to be in the form of column1 = value if record exists, Column2 = value if record exists.
I tried using joins, but didn't get that far with those. I could try to use INSERT... UPDATE ON DUPLICATE KEY, but I want to update records that need to have unique combinations of values, not unique primary keys.
For example: IP | Account | CharID | Count | Updated
IP | Account | CharID should be unique together
Count | Updated should be updated.
I have no clue how I can make sure such a record exists without SELECTing it first, and I don't want to force errors by blindly INSERTing it. I think I need to SELECT, and if I must I'd like to select another table in the same statement, and that's why I ask the question above.
Hope my rather vague explanation tells you what I want. |
|
Back to top |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Tue Dec 12, 2006 17:20 Post subject: |
|
|
It's difficult to give detailed advice without knowing the table and data structure, but IF you really can not do it with a join, subselects (or subqueries in MySQL) might help you out:
http://dev.mysql.com/doc/refman/5.0/en/subqueries.html _________________ Papillon |
|
Back to top |
|
|
pdwalker
Joined: 09 Aug 2005 Posts: 22
|
Posted: Tue Dec 12, 2006 20:49 Post subject: insert <record> on duplicate key update |
|
|
mysql has a non standard insert statement that allows you to update a record if the record already exists.
http://dev.mysql.com/doc/refman/4.1/en/insert.html
Perhaps you could use this to solve your problem? |
|
Back to top |
|
|
Disco
Joined: 06 Dec 2006 Posts: 152
|
Posted: Wed Dec 13, 2006 16:00 Post subject: |
|
|
What I am looking for is an UPDATE if exists INSERT statement. It may seem to be equivalent to INSERT if exists UPDATE but it isn't as you select on a full WHERE clause isntead of the primary key.
Say I have a table A that has the fields a1, a2, a3, a4 and a table B with b1, b2, b3
I also have a variable CharID, a variable Week, and a variable Account
I want to update a3, a4 if a1 = CharID and a2 = Week and b3, b4 if b1 = CharID and b2 = Account. If either record doesn't exist I want to create a new one which I can update with the next call. In pseudocode:
Code: | SELECT a1 FROM A WHERE a1 = CharID AND a2 = Week
IF (a1 == CharID){
UPDATE A (values a3,a4) WHERE a1 = CharID AND a2 = Week
}
ELSE{
INSERT INTO A (values a1,a2,a3,a4)
}
SELECT b1 FROM B WHERE b1 = CharID AND b2 = Account
IF (a1 == CharID){
UPDATE B (values b3,b4) WHERE b1 = CharID AND b2 = Account
}
ELSE{
INSERT INTO B (values b1,b2,b3,b4)
} |
I want to use a minimal amount of queries, though. I thought about checking both tables in one go, and trying to combine INSERT and UPDATES where possible as well. |
|
Back to top |
|
|
Disco
Joined: 06 Dec 2006 Posts: 152
|
Posted: Wed Dec 13, 2006 16:35 Post subject: |
|
|
Nevernermind this, I just learned about combined unique indexes! |
|
Back to top |
|
|
|