I have a MySQL query that goes as follows (using Zend_Db):
$sql = $handle->quoteInto("UPDATE board SET rank=rank+1 WHERE post_id=?", $postid);
$handle->query($sql);
(Rank isn't an auto-incrementing PK).
I would like to now retrieve the value of rank without preforming another query.
I've tried $handle->lastInsertId(); but it doesn't seem to work , since I didn't use MySQL's natural auto-incrementing method (I can't - rank is the rank of a post. I either ++ or -- it.)
Any way to do this with preforming another query? A function that will return the last changed value?
I don't believe this is possible - you'll just have to do a SELECT.
You can use the LAST_INSERT_ID function that MySQL provides to set a value and then make it available via the mysql_insert_id() C function that the $handle->lastInsertId(); relies on.
The following is an updated version of your code snippet with the LAST_INSERT_ID changes made to it:
$sql = $handle->quoteInto("UPDATE board SET rank=LAST_INSERT_ID(rank+1) WHERE post_id=?", $postid);
$handle->query($sql);
Let me know if you have any questions.
HTH,
-Dipin
Related
Within a MySQL query, is it possible to put a PHP function around a field name in order to change/replace its value?
SELECT * FROM my_table WHERE url_title(field_name) = '$variable'
The reason for asking is that the '$variable' in my URL which the query will use is an edited version (using Codeigniter's url_title function) of its true value eg. $variable = 'dangelo' whereas its true value in field name is "D'Angelo".
You can implement the url_title function as a MySQL stored procedure, which would require translating the PHP code of that function to a MySQL stored procedure.
Note that the performance would not be great due to having to call this function for every row on each query.
The more typical solution is to have another field for the slug, pre-generate the values for each article's slug. On the query, you would compare $variable to the new field.
Yes it's possible. But not at all recommended because it wouldn't be able to make use of the index. Create another column with the actual value you want to find and add an index to that column.
I want to get the last affected table name (after insert).
I tried with mysql_insert_id() but i got only id.
I want table name also.
Can anyone give me the idea for my problem
It's a strech... But if :
you are running mysql 5.6.3 +
you still have access to the insert query (let's say it's $query)
you are sure it's an insert query (because, hey, you know you want last_insert_*, don't you?)
You can try:
$row = mysql_fetch_assoc(mysql_query("explain $query"));
$table = $row['table'];
From mysql 5.6.3+ you can combine explain with a insert into query.
This should return only 1 row, I think.
I dont have mysql 5.6.3+ myself to test it.
You can override mysql_query function as defined in this post, save you last call table name in global var or session and pray for last called insert finish last.
// THIS JUST SAMPLE... use code from link below ^
function custom_mysql_query($query){
if(strstr('INSERT',$query)){
/*GET YOUR TABLE NAME WITH REGEX*/
}
basic_mysql_query($query);
}
This is very very very bad solution for me. But in theory will work.
You mention in your comment that you're using a common function to apply the changes in, preventing you from 'knowing' what the last table is you inserted in.
If that's the case: your logic is flawed.
MySQL is not gonna tell you what the last table is it did an INSERT in. You will have to write a hook in your function where you last know what table you're gonna update. No matter what function you use, you must specifiy a table name at some point, before executing the insert. You store the table name at that point.
You can do that in many ways, depending on your needs:
store it in a mysql table (last_updated_table with only 1 column,
for example)
store it in a variable (if you only need it in the
same request)
store it in a session (I wouldn't opt for this)
You can use the information_schema database if you have one :
SELECT TABLE_SCHEMA, TABLE_NAME, UPDATE_TIME
FROM TABLES
ORDER BY UPDATE_TIME DESC
LIMIT 0,1
Use this after your query, and you'll get the affected table.
I'm working on a portal / large website and I have a question as to how to optimise my mySql / PDO queries in a special case.
I developed it this way : when I'm inserting an iD (unique / primary) I do the following code to find out the highest unused id in a specific table, and then do an INSERT with that id ($next_avail).
After a short chat last days on stackoverflow I got the ideea that AUTO_INCREMENT is best for this action.
But now, I realize that in most of the cases I also use $next_avail (the value of the AUTO_INCREMENT how it would be) to insert in other tables as a column, as well.
So my code makes sense for these inserts.
My question is, how would this code below work for millions of rows as speed, for each insert I do depends on it.
Please write comments and ask me to clarify what is not clear for you, in this question.
Thanks, Adrian
$next_avail = 1 ;
$stmt = $db->prepare("SELECT news_id from mya_news ORDER BY news_id DESC LIMIT 1");
$stmt->execute();
while ( list($id) = $stmt->fetch(PDO::FETCH_BOTH) ) {
$next_avail = $id + 1;
}
You don't need to do that, just use an auto_increment in your table, and also use the PHP functions to get the last_inserted_id mysql_insert_id()
take a look to this sites:
http://php.net/manual/en/function.mysql-insert-id.php
this one is with PDO
http://php.net/manual/en/pdo.lastinsertid.php
Possibly use max rather than ordering the results and using a limit.
However this is very risky. A chance that 2 bits of processing will both get the same $next_avail at the same time. I would suggest changing the order you insert rows (or even inserting a dummy row to get the next id, and updating the row later on) to use the AUTO_INCREMENT column value
I'm trying to count a table row and add 1 on the outcome, I have this snippet of code.
$countQuery = "SELECT COUNT(id) FROM donations";
$outcomeQuery = mysql_query($countQuery);
$countUp = mysql_fetch_array($outcomeQuery);
$plusOne = 1;
$outcome = $countUp;
echo $outcome[0]
or die(mysql_error());
But this gives me the error:
Fatal error: Unsupported operand types
I need this so I always have a unique number that's not used by a previous donator.
You could use:
SELECT COUNT(id)+1 as IDCount FROM donations
as your query instead. This will save you any mucking about in PHP to do the math. The array you pull back will have the number that you want right off the bat.
Edit: The better alternative however is to use a column type that increments automatically. In MySQL, this is done with the syntax auto_increment in the create table syntax.
Using this, you never actually have to insert a value, but rather, you pass it a NULL as follows (assuming that ID is the field with Auto_increment on it:
insert into tableName (ID,Name) values (null, 'Fluffeh');
So you see you don't give it any values for the ID column - the database takes care of using the right number.
use simple php
$countQuery = mysql_query("SELECT id FROM donations");
$count=mysql_num_rows($countQuery);
$count+=1;
It's dangerous to rely on COUNT to give you a unique number. What happens if two processes execute this query, and then both try and commit: you suddenly have the same value twice.
It would be much safer to implement some kind of sequence function independent of your table contents. This link shows one possibility:
http://forums.mysql.com/read.php?61,143867,238482#msg-238482
This question is for a MySQL database. I suggest you use the AUTO INCREMENT field type.
As you are using PHP, if you need to know the id after inserting a record, use:
mysql_query("INSERT INTO mytable (1, 2, 3, 'blah')");
$id = mysql_insert_id();
See mysql_insert_id().
Using
4 random generated numbers to make 100% sure there are no duplicates
will not make 100% sure there are no duplicates. Don't re-invent the wheel. This is how the problem of ensuring unique incrementing identifiers are used has been solved, you don't need the embarrassment of a homebrew solution that doesn't always work.
Let's say you're making a CodeIgniter model's function which creates a user.
function create($data){
$sql = "INSERT INTO people (fname,lname,age,location) VALUES(?,?,?,?)";
$this->db->query($sql, $data);
}
function get($id){
$sql = "SELECT * FROM people WHERE id = ? LIMIT 1";
return $this->db->query($sql, array($id));
}
You want create() to create the user but return the same thing as get() as an associative array containing the user id and the other inserted info.
Obviously this could be done by making an array containing the $data elements. But think about a lot of fields.. it makes the code ugly and unsecure to modify because you'll deal with numerical arrays not associative.
Is there any way for the MySQL to return the inserted record with the id without having to query again using SELECT for better performance and neat looking code?
You can't insert and return the row in the same query with MySQL.
But you can get the last inserted id (I'm guessing the id field is autogenerated) with ->insert_id. You can use that to call get from your create function.
you could wrap the whole thing (INSERT plus SELECT) in a procedure, which would save you a callout to the database, and at the same time ensuring you read exactly what exists in the database (for e.g. autoincrement columns or defaulted values). But procedures aren't everybody's cup of tea.
In MySQL, no, there's no way to do what you want. Some databases (at least PostgreSQL) support a INSERT ... RETURNING syntax, which allows this. Unfortunately, you will either have to re-query the newly inserted row, or mangle a return value out of the input value in your client code.
As #Flimzy said you cannot do it in one query ala Postgres with its RETURNING clause.
Your best bet is to use MySQL's LAST_INSERT_ID() which is guaranteed to return the newly created record's ID and its scoped to the current session so there is no issue of getting a race condition