Update multiple tables with ZF2 update class - php

I'm trying to use the zend framework update class: http://framework.zend.com/manual/2.2/en/modules/zend.db.sql.html#zend-db-sql-update
to create something like the statement found here:
http://dev.mysql.com/doc/refman/5.0/en/update.html
UPDATE items,month SET items.price=month.price WHERE items.id=month.id;
I've tried passing an array to ->table but it fails on the string conversion.
// UPDATE `Array`
$update->table(['table1', 'table2'])
I've tried creating an escaped string but it ends up double escaped when converted to sql.
// UPDATE ``table1`,`table2``
$update->table("`table1`,`table2`")
I've tried cheating and used implode to use the glue the tables together
// UPDATE `table1``,``table2`
$update->table(implode("`,`", ['table1','table2']))
Does anyone have a clean answer to this issue?

After further research, I don't think it can be done. The reason I say that is because the query you've proposed may be too resource intensive. After looking for an alternate option, I've come across Update one MySQL table with values from another. However, that I'm aware of, there's no join option on an Update object. So at least at this stage, I don't believe it can be done.

Are you trying to write sql like: "update tableOne, tableTwo set ...." !! I do not think it is possible in sql. As this kind of syntex not supported by mySql so do zend. here is zend table method-
public function table($table)
#param string|TableIdentifier $table
parameter is simply string or TableIdentifier. So you have to write two sql in zend
$update->table('table1');
$update->set(array('foo' => 'bar', 'baz' => 'bax'));
.......
........
$update->table('table2');
$update->set(array('foo1' => 'bar', 'baz1' => 'bax'));
Hope it will help you.

Related

PDO - run unprepared statement containing "?" [duplicate]

For detecting the existence of a key in a hstore, I need to run a query like this:
SELECT * FROM tbl WHERE hst ? 'foo'
However, that gives me a PDOException:
PDOException: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound: SELECT * FROM tbl WHERE hst ? 'foo'
Is there any way to escape the question mark so PDO won't pick it up as a placeholder? I've tried with up to four backslashes, as well as a double question mark (??), but nothing seems to persuade PDO to leave the question mark alone.
Use the function call form. According to the system catalogs, the hstore ? operator uses the exist function:
regress=# select oprname, oprcode from pg_operator where oprname = '?';
oprname | oprcode
---------+---------
? | exist
(1 row)
so you can write:
SELECT * FROM tbl WHERE exist(hst,'foo');
(Personally I'm not a big fan of hstore's operator-centric design and documentation, I think it discards the useful self-documenting properties of a function based interface without any real benefit and I usually use its function calls rather than its operators. Just because you can define operators doesn't mean you should.)
I had the same problem when searching on JSONB data. The full question is here
SELECT * FROM post WHERE locations ? :location;
The workaround on PostgreSQL 9.5 is similar:
SELECT * FROM post WHERE jsonb_exists(locations, :location);
I also opened a ticket at PHP bug tracing system
Update
As Diabl0 mentioned, the proposed solution work but does not use the index.
Tested with:
CREATE INDEX tempidxgin ON post USING GIN (locations);
I suggest you disable PDO native prepared statement so question marks will be ignored:
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);

how to get the where clause in string format using CakePHP3 ORM?

In CakePHP3, there is a ORM that helps with building queries.
From the documentation, I can see that
$query = $articles->find(); // build a query that has not run yet
$query->where(['id' => 1]); // Return the same query object
So in this case, I want the string
WHERE `articles`.`id` = 1
After much googling, I found out that there is a way to return just the where clause of a query object.
$query->where(['id' => 1])->clause('where'); // Return the where clause in the form of a QueryExpression
More googling leads me to find out how to get the QueryExpression to spit out string representation
$query->where(['id' => 1])->clause('where')->sql($valueBinder); // Return the where clause in string format
Here is my problem. I don't know what the $valueBinder is supposed to look like. I don't know how to initialize it.
I am also happy not to use ValueBinder as long as I can get the where clause in string format using CakePHP 3 ORM and in the right SQL dialect. Please assume I am using MySQL.
Please advise.
EDIT
I tried to use $query->valueBinder() as the $valueBinder.
It is empty and does not contain the associated c:0 to the value 1.
To directly answer your question, you can get the SQL for any clause this way:
$binder = new \Cake\ORM\ValueBinder();
$query->clause('where')->sql($binder);
That will return the SQL with the correct placeholders, not with the values to be used. The values live in the $binder variable and are used for statement objects.
As I can see, you only wanted to preserve the internal structure of the where clause to pass it to another query in a different request. Your solution is fine, but I'd like to add that you can also encode a full conditions tree from an existing query:
$where = serialize($query->clause('where'));
$anotherQuery->where(unserialize($where)); // A query in another request
In any case, you need to be careful with what you are unserializing as taking it directly from user input will certainly lead to security problems.
You can choose to omit this param if you like. Please see http://api.cakephp.org/3.0/class-Cake.Database.Query.html#_sql
In addition, you can use the Query member function traverse($visitor, $parts) to isolate the where clause. $visitor is a function that takes a value and a clause. You define the behavior of $visitor. $parts is an array of clause names. I suggest passing array('where') into this param.
My workaround is that I store the conditions in json string format.
Using the same example, what I do is
$data['conditions'] = json_encode(['Articles.id' => 1]); // encode into JSON string
$this->DynamicRules->patchEntity($dynamicRule, $data); // use in edit action of DynamicRulesController
then when I need to reuse the conditions, I do:
$articlesTable = TableRegistry::get('Articles');
$query = $articlesTable->find(); // new query for Articles
$rule = json_decode($dynamicRule->conditions, true); // get back the conditions in associative array format
$query->where($rule); // re-assign the conditions back
This got me what I ultimately wanted.

Update a row by 1 in CakePHP

I have searched for this question and found many similar answers like this one
Update a row +1 in CakePHP
and this is what the accepted answer looks like
$this->Widget->updateAll(
array('Widget.numberfield' => 'Widget.numberfield + 1'),
array('Widget.id' => 1)
);
Now iam using this query in cakephp3.
Here is what mine looks like
$Questions=$this->loadModel('Questions');
$Questions->updateAll(
array('questions.trend' => 'questions.trend + 1'),
array('questions.description' => $undashed_title)
);
Every thing is working fine and query's are executing but when i check debugger for sql log, Here's what i found
UPDATE questions SET questions.trend = 'questions.trend + 1' WHERE questions.description = 'What type'
But my value in database is not updating like it should be
(Iam saying this beacuse i also have copied this query on phpmyadmin console and its not working )
I believe the query should look like this
UPDATE questions SET questions.trend = questions.trend+1 WHERE questions.description = 'What Type'
Any help would be appreciated ,Thanks :)
Well, as i said on comments, CakePHP 3 diverge a value from a expression, and the increment thing that you trying to do is a expression, to solve your "problem" you shall dig deep on CakePHP docs, and so you will find this http://book.cakephp.org/3.0/en/orm/saving-data.html#bulk-updates, yeah, right what you want. So, it becomes:
// load your beloved model
$questions = $this->loadModel('Questions');
// create a beauty expression
$expression = new QueryExpression('questions.trend + 1');
// execute a update with the beauty expression
$questions->updateAll(
array('questions.trend' => $expression),
array('questions.description' => $undashed_title)
);
And don't forget to load QueryExpression's namespace with use Cake\Database\Expression\QueryExpression;.
Yes, this is the wrong way to do on CakePHP 3, you shall the CakePHP's ORM, and move the increment thing to the model layer.

Laravel Fluent Query Builder Update Query

I want to add two columns while using update, like this:
Update purchase_stock inner join stock on purchase_stock.fkstockid=stock.stockid SET currentavailable=currentavailable+subquantity where fkorderid='1';
Here is the current Fluent code:
DB::table('purchase_stock')->join('stock','stock.stockid','=','purchase_stock.fkstockid')->where('fkorderid',$orderId)->update(array('currentavailable'=>'currentavailable'+'subquantity'));**
But it throws error as below:
"error":{"type":"Symfony\\Component\\Debug\\Exception\\FatalErrorException","message":"syntax error, unexpected '=>'"
Does any one have solution?
You were very close with your fluent attempt, but there were two issues:
The plus sign needs to be inside the quotes, since you want the math done in SQL, not in PHP.
Need a DB::raw() around the value so Laravel doesn't think you're actually trying to set it to the string "currentavailable + subquantity"
So the final product looks like this:
DB::table('purchase_stock')
->join('stock', 'stock.stockid', '=', 'purchase_stock.fkstockid')
->where('fkorderid', $orderId)
->update(['currentavailable' => DB::raw('currentavailable + subquantity')]);
Мaybe you need to set these two fields from which tables. Exampl. DB::table('purchase_stock')->join('stock','stock.stockid','=','purchase_stock.fkstockid')->where('fkorderid',$orderId)->update(array('stock.currentavailable'=>'stock.currentavailable'+'stock.subquantity'));
Ohk!
I already tried this one but it is not working
As of now I am using DB::statement('') and it's working
So I have written whole update query within statement and it's working as somewhere I have read that it will not be helpful to return result set but will work with insert or update.

quickest way to update a Mysql Database

Just wondering what the best way to update an entire (large) database would be.
Bascially I have inherited a DB which had character issues, with some help I have sorted the character issues going forward (being written in) however the existing data needs cleaning up.
There was a good suggestion that I could use utf_decode to clean all this up - I have tried this on a wrong value in the page itself (when pulled in) and it works great.
As there seems to be a lot of tables, and alot of data, what's the best / quickest way to sweep all the data in the entire DB by using utf_decode ?
Thanks
Thanks for the comments, I can't seem to comment directly so dropping as message in here - I will have a look through and give them a go ! thanks.
Have you tried using the MySQL function CONVERT? Depending on your data, you may be able to update tables in a single statement, such as "UPDATE mytable SET myfield = CONVERT(myfield USING utf8)".
http://dev.mysql.com/doc/refman/5.0/en/charset-convert.html
Fetch all the data, convert it and insert it as:
INSERT INTO table VALUES (id, text)
(1, 'utf8'), (2, 'utf8'), (3, 'utf8')
etc.
Goes faster then to do a php loop with multi INSERT queries.
EDIT:
If you use a nice array, you could run a smooth system to do this:
$arr = array('users' => array('user_id', 'text', 'username', 'first_name')));
foreach(array_keys($arr) as $h) {
$query = mysql_query("SELECT * FROM {$h}");
while($row = mysql_fetch_object($query)) {
// Loop thingies, utf8_decode then and stuff
}
// Then implode them nicely and use above query
}
Tell me if you need more code example.

Categories