I'm trying to update a value of a column using the codeigniter query function like this:
$this->db->query("UPDATE table SET val = val + 1 WHERE name = 'xxxxx');
Is there any way to get the result of this update in the same query function? I have to do a select query in order to do it and it's dangerous because of the amount of users this application is managing.
If there is another query in between the update and the select, the result would not be correct.
Thanks!
Use transaction and for update. This is an example from zend, which is a similar kind of db accessing thing:
$db->beginTransaction();
$val = $db->select()->forUpdate()->from('table', 'val')->orderBy('val DESC')->limit(1)->query()->fetchColumn();
$db->update('table', 'val = '.($val+1), 'name = "xxx"');
$db->commit()
The for-update with the transaction prevents another query interfering.
Learn more about for update here: http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html
and about codeigniter transactions here: http://ellislab.com/codeigniter/user-guide/database/transactions.html (thanks to #Nanne for that)
Related
I am trying to execute a query in PHP, but this code wouldn't work for some reason, it doesn't detect the keywords at all(DECLARE, SELECT, WHERE). Is there anything I can do and after all can I even use DECLARE in PHP as a mySQLi statement.
$sql2 ="DECLARE #MaxID INT; SELECT #MaxID = MAX(productID) FROM products; UPDATE sunglasses SET sunglassesId = #MaxID WHERE sunglassesId = 0;";
After all I am trying to update a field in Table1 where its initial value is 0 with a value from a field in Table2.
Hope that made sense.
P.S tried this query in Microsoft SQL Management studio and it worked, in PHP it doesnt.
change your query to this and you don't need any other variable:
UPDATE sunglasses
SET sunglassesId = (SELECT MAX(productID) FROM products)
WHERE sunglassesId = 0;
I have a function that is designed to copy a product with all attributes with help of sql querys. My problem is to return new_product_id to php after completion.
If i run sql script in phpmyadmin all is working.
If i run sql script with php function all is working.
What i need help with is how to assign mysql-set-variable: #new_product_id from last query to php variable that I want to return.
----- sql query ------
CREATE TEMPORARY TABLE tmptable SELECT * FROM product WHERE id='19' AND site_id='1';
UPDATE tmptable SET id = 0,parent_id='19',status_id='1',name_internal=concat('NEW ',name_internal);
INSERT INTO product SELECT * FROM tmptable;
SET #new_product_id = LAST_INSERT_ID();
DROP TABLE tmptable;
CREATE TEMPORARY TABLE tmptable SELECT * FROM product_abcd WHERE product_id='19' AND site_id='1';
UPDATE tmptable SET product_id = #new_product_id,id=0;
INSERT INTO product_abcd SELECT * FROM tmptable;
DROP TABLE tmptable;
CREATE TEMPORARY TABLE tmptable SELECT * FROM product_efgh WHERE product_id='19' AND site_id='1';
UPDATE tmptable SET product_id = #new_product_id,id=0;
INSERT INTO product_efgh SELECT * FROM tmptable;
DROP TABLE tmptable;
(Here is more correct SQL insert statements)
SELECT #new_product_id AS new_product_id;
----- sql query ------
----- php function (not complete)------
This function is working making a new copy of product, code below is not complete but works so please only focus on multiquery part.
//return 0 for fail or new product_id (!=0) for success
public function copyProduct($data){
$res=0;
//if something, build sql-query as
$sql="sql from above";
//if we have a query to run
if(!empty($sql)){
//this is multi query, use correct function
if ($this->connect()->multi_query($sql) === TRUE) {
//loop it
while ($this->connect()->more_results()){
$result=$this->connect()->next_result();
}//while more results
}//if multiquery ok
return $res;
}//end function copy
----- php function (not complete)------
above code works, i get a nice copy of product with
result =0 for fail and
result 1 for success, (this works)
How i would like it to work is
result= 0 for fail and
result= new_product_id for success
so i can redirect user to the newly created product and therefore save user one click.
Results from query, same from phpmyadmin as from php (all good so far, no incorrect querys at this time)
Mysql returned empty results (no rows) (create temporary table)
1 row affected (update tmpt table)
1 row insert (insert into product)
mysql returned emtpy result (set $new_product_id)
mysql returened empty results (drop tmp table)
mysql returned empty result (create temporary table)
mysql x row affected (update tmp table)
mysql x row affected (insert into table)
mysql returned empty results (drop table tmptable)
mysql returned empty results (create temporary table)
.... N.....
last query "showing rows 0-0 ( 1 total) (select #new_product_id)
new_product_id=25
What have I tried?
I placed the select variable as my final query, i thought it was smart only check last query and assign variable there, but i failed due to php mysqli fetch_assoc is not possible on non object.
so next up was not so bright, i know i have 16 results from mysql and i only need the result from one of them, but anyway i places this inside multiquery
----- php function (not complete)------
This function is working making a new copy of product, NOT WORKING assigning new_product_id
//return 0 for fail or new product_id (!=0) for success
public function copyProduct($data){
$res=0;
//if something, build sql-query as
$sql="sql from above";
//if we have a query to run
if(!empty($sql)){
//this is multi query, use correct function
if ($this->connect()->multi_query($sql) === TRUE) {
//loop it
while ($this->connect()->more_results()){
//insert,update,drop will return false even if sql is ok, this would be sufficient for us now
if ($result = $this->connect()->store_result()) {
$row = $result->fetch_assoc();
if(isset($row["new_product_id"])){
//new return value of newly copied product
$res=$row["new_product_id"];
$result->free();
}
}
$result=$this->connect()->next_result();
}//while more results
}//if multiquery ok
return $res;
}//end function copy
----- php function (not complete)------
Checking other questions on stackoverflow recommended sending multiple normal querys, this seems like a bad solution when multi_query exists.
checking php library for multiquery did me no good, i cant understand how it works, as many others pointed out the documentation seems like a copy from another function.
Remember that multi_query() sends a clump of SQL queries to MySQL server but waits for the execution of only the first one. If you want to execute SQL using multi_query() and get only the result of the last query ignoring the previous ones then you need to perform a blocking loop and buffer the results into PHP array. Iterate over all results waiting for MySQL to process each query and once MySQL responds there are no more results you can keep the last fetched result.
For example, consider this function. It sends a bunch of concatenated SQL queries to the MySQL server and then waits for MySQL to process each query one by one. Every result is fetched into PHP array and the last available array is returned from the function.
function executeMultiQueryAndGetOnlyLastResult(mysqli $mysqli):array {
$mysqli->multi_query('
SELECT "a";
SELECT 2;
SELECT "val";
');
$values = [];
do {
$result = $mysqli->use_result();
if ($result) {
// process the results here
$values = $result->fetch_all();
$result->free();
}
} while ($mysqli->next_result()); // next_result will block and wait for next query to finish on MySQL server
$mysqli->store_result(); // Needed to fetch the error as exception
return $values;
}
Obviously it would be much easier to send each query separately to MySQL instead. multi_query() is very complicated and has very limited use. It can be useful if you have a number of SQL queries which you cannot execute separately via PHP, but most of the time you should be using prepared statements and send each query separately.
Another one bites the dust, I gave up and defined an array of sql querys from 0 to 14 and run it as mysqli->query() instead. Thank you all for comments and your time.
You could try using .multi_query() for all the queries in your operation except the last one, the SELECT that returns the id you want. Then run that SELECT as a single query.
This is a robust solution to your problem: #-variables belong to MySql connections and persist for the lifetimes of those connections.
And, it makes for clean and predictable operation of your software. When you need a result set returned to your program, use a single query.
I'm having what may be the dumbest issue.
I'm using phpmyadmin and when I query a table using OR it does not return all values.
This is the query that is not returning all values:
SELECT * FROM ecrdatabase.ecrtable m WHERE m.ecrChangeOwner = '$partialOwner' OR m.ecrInitByName = '$partialOwner'.
Here, $partialOwner is passed from $_GET['user'].
Some of the rows are returned - just not all of them. I have a php page that queries the database and I have tried running the query directly on the database through phpmyadmin using query:
SELECT * FROM ecrtable WHERE ecrChangeOwner = 'ecunningham' OR ecrInitByName = 'ecunningham'.
Both results from the the direct query and php page return the same number of rows.
I have also tried:
SELECT * FROM ecrtable WHERE (ecrChangeOwner = 'ecunningham' OR ecrInitByName = 'ecunningham').
What am I missing? I have more complex queries that run fine. Please tell me I'm just missing something stupid...
You really should be using prepared statements here, first of all. You are wide open to injection attacks.
Second, how do you know that this query does not return all the rows? What queries have you done to verify that this one is wrong?
If you run a union what do you get:
SELECT * FROM ecrtable WHERE ecrChangeOwner = 'ecunningham'
UNION ALL
SELECT * FROM ecrtable WHERE ecrInitByName = 'ecunningham')
I'm using a SELECT query to obtain a variable using mysql_fetch_assoc. This then puts the variable into an UPDATE variable to put the returned value back into the database.
If I hard code the value, or use a traditional variable and it goes in just fine, but it doesn't work when using a value previously retrieved from the database. I've tried resetting the array variable to my own text and that works.
$arrgateRetrivalQuery = mysql_query(**Select Query**);
$arrGate = mysql_fetch_assoc($arrgateRetrivalQuery);
$arrivalGateTest = $arrGate['gatetype'];
$setGateAirportSQL = "UPDATE pilots SET currentgate = '".$arrivalGateTest."' WHERE pilotid = '".$pilotid."'";
$setGateAirportQuery = mysql_query($setGateAirportSQL);
// Close MySQL Connection
mysql_close($link);
This will just make the field to update have nothing in it, however whenever I remove the variable from the SELECT to one I define, array or not, it will work.
Hope this is clear enough. Thanks in advance.
Is arrivalGateTest a number or a string? How did you try to put another value in the query? If you are sure the previous query returns a value, try to write: $setGateAirportSQL = "UPDATE pilots SET currentgate = '$arrivalGateTest' WHERE pilotid = '$pilotid'";.
Just change your sql to inlcude a subquery.
You could use the following general syntax:
UPDATE pilots SET currentgate = (SELECT gate FROM airport WHERE flight='NZ1') WHERE pilotid='2';
which is demonstrated on this fiddle
This saves the extra query and more accurately describes what you are trying to achieve.
WARNING - test it carefully first!
I just realized that you cannot use:
$this->db->join()
with
$this->db->update()
It seems the "join" is executed by codeigniter alright, but is not used in the query, seen after an update on the base table obtained with: $this->db->last_query();
I saw that there was no join. Then I tried an update on the joined table thinking the join would only been used if needed, but I did not work and told me the error 1054 "Unknown column XXX in where clause".
Is there a way to force codeigniter? The way I built my software, I REALLY don't want to build all the different parts of the queries myself (join, where) and the call $this->db->query().
NOTE: I saw these links:
Codeigniter active record update statement with a join
Is it possible to UPDATE a JOINed table using Codeigniter's Active Record?
codeigniter - database : how to update multiple tables with a single update query
but if someone knows a cleaner way it would be nice, because these solutions are not working with my case, since I was using the same joins in a "preProcessing()" method that uses the joins for a preview of the changes, then the same "preProcessing()" method is used for the replacement
Ok well I managed to find a "clean" solution, using codeigniter's join, set, etc. So what's cool is that you will have all CI's benefits of using $this->db->join(), $this->db->join(), etc. like escaping and adding quotes.
So first do all your CI stuff:
$this->db->join(..) // Set all your JOINs
$this->db->set(..) // Set your SET data
$this->db->where(..) // Set all your WHEREs
Then you can build the query using Active Record's ready, cleaned and escaped query elements:
// JOIN
$sql = "UPDATE $this->baseTable ";
$sql .= implode(' ', $this->db->ar_join);
// SET
$sql .= ' SET';
$setArray = array();
foreach ($this->db->ar_set as $column=>$newValue)
array_push($setArray, " $column = $newValue");
$sql .= implode(',', $setArray);
// WHERE
$sql .= ' WHERE '.implode(' ', $this->db->ar_where);
$this->db->query($sql);
If someone has a better solution, I will gladly accept it and use it instead