I dont get it ... I tested a lot but dont get why a SQL error appears ...
In my case I use a function to generate a mysql-query to get all extra-field items from the database (K2 - Component).
It is used like this:
public static function readExtraFields ($fields, $as = 'array') {
if (!is_array($fields)) $fields = json_decode($fields);
$result = array();
$whereId = array();
$allFieldValues = array();
foreach ($fields as $field) {
$whereId[] = "`id`='".$field->id."'";
$allFieldValues[$field->id] = $field->value;
}
$query = "SELECT * FROM `#__k2_extra_fields` WHERE " . implode(" OR ", $whereId);
$queryResult = self::execQuery($query);
[...]
In this method a query will be generated like this (I printed it out)
SELECT * FROM `#__k2_extra_fields` WHERE `id`='1' OR `id`='2'
This is fine. When I execute the methode execQuery with the given query this error appears:
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 SQL=SELECT * FROM `j7req_k2_extra_fields` WHERE
Thats all ... I dont get it. My method to execute my mysql-query:
public static function execQuery ($query) {
$db = JFactory::getDbo();
$db->setQuery($query);
$result = $db->loadObjectList();
return $result;
}
For testing I printed out the Query (the above) and set $query to the printed query and this runs without any problems like the way it should work ... So the query which is given is right ... what can be the problem ?
Edit 1
In my execQuery method I printed the $db out. This reuslt is given (you can find the query at the bottom of this object)
JDatabaseDriverMysqli Object
(
[name] => mysqli
[nameQuote:protected] => `
[nullDate:protected] => 0000-00-00 00:00:00
[_database:JDatabaseDriver:private] => podopraxis
[connection:protected] => mysqli Object
(
[affected_rows] => 1
[client_info] => mysqlnd 5.0.11-dev - 20120503 - $Id: bf9ad53b11c9a57efdb1057292d73b928b8c5c77 $
[client_version] => 50011
[connect_errno] => 0
[connect_error] =>
[errno] => 0
[error] =>
[error_list] => Array
(
)
[field_count] => 1
[host_info] => localhost via TCP/IP
[info] =>
[insert_id] => 0
[server_info] => 5.6.16
[server_version] => 50616
[stat] => Uptime: 48979 Threads: 1 Questions: 6461 Slow queries: 0 Opens: 163 Flush tables: 1 Open tables: 155 Queries per second avg: 0.131
[sqlstate] => 00000
[protocol_version] => 10
[thread_id] => 203
[warning_count] => 0
)
[count:protected] => 45
[cursor:protected] =>
[debug:protected] =>
[limit:protected] => 0
[log:protected] => Array
(
)
[timings:protected] => Array
(
)
[callStacks:protected] => Array
(
)
[offset:protected] => 0
[options:protected] => Array
(
[driver] => mysqli
[host] => localhost
[user] => root
[password] =>
[database] => podopraxis
[prefix] => j7req_
[select] => 1
[port] => 3306
[socket] =>
)
[sql:protected] => SELECT * FROM `#__k2_extra_fields` WHERE `id`='1' OR `id`='2'
[tablePrefix:protected] => j7req_
[utf:protected] => 1
[errorNum:protected] => 0
[errorMsg:protected] =>
[transactionDepth:protected] => 0
[disconnectHandlers:protected] => Array
(
)
)
It looks like your query fired in execQuery() function is missing the condition statement after "WHERE" clause of query.
Please make sure below part of condition comes in your query:
`id`='1' OR `id`='2'
let me know if I am not getting well about your question?
Also try to post here whole $db object by printing as below:
echo "<pre />";print_r($db);exit;
Related
When I select a column in SQL Server and then print it, 3 becomes 3.0.
This is my connection:
$sql = new PDO("sqlsrv:Driver=$driver;server=$server,$port;Database=$database;ConnectionPooling=0", $uid, $pwd,
array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
)
);
This is my SELECT:
$sth = $sql->prepare("SELECT column FROM table
WHERE column2 = :value2");
$params = array(':value2' => $_POST['value2']);
$sth->execute($params);
$result = $sth->fetchAll(\PDO::FETCH_ASSOC);
echo json_encode($result);
In SQL Server database: 3
In echo: 3.0
What can be the reason for adding .0?
So here's the thing.
I'm querying the database using Doctrine 2.5 and I'd like to use Doctrine's createQuery() method to do it. The reason is that Doctrine 2 hydrates the results in a camelCase manner, and my column names are all with underscores. And since most of the simple queries work fine with createQuery (or even with the query builder) I'd like to move all native MySQL queries to Doctrine's DQL (to get all results in camelCase so that's a standarized results). Either that or you guys can teach me how to make Doctrine 2 return the results in the same way that the columns are in the database... xD
I have the following query:
$sql = '
SELECT sp.*, so.user_id
FROM shop_order so
INNER JOIN shop_payment sp ON(so.payment_id=sp.id)
WHERE so.id = '.$orderID;
$stmt = $em->getConnection()->prepare($sql);
$stmt->execute();
$result = $stmt->fetch();
This results in the following result:
Array
(
[id] => 14
[payment_type_id] => 2
[flag] => boleto_bb
[tid] =>
[billet] => 1
[parcel_quantity] =>
[cart_name_holder] =>
[cart_date_holder] => 1999-12-01
[cart_number_holder] => 0
[datecreated] => 2017-08-30 14:51:25
[dateupdate] => 2017-08-30 16:36:18
[status] => 2
[user_id] => 16
)
But if I do it like this:
$query = $em->createQuery('
SELECT sp, so.userId
FROM ShopOrder so
INNER JOIN ShopPayment sp WITH (so.paymentId = sp.id)
WHERE so.id = ' . $orderID);
$result = $query->getArrayResult();
I get the following result:
Array
(
[0] => Array
(
[0] => Array
(
[id] => 14
[paymentTypeId] => 2
[flag] => boleto_bb
[tid] =>
[billet] => 1
[parcelQuantity] =>
[cartNameHolder] =>
[cartDateHolder] => DateTime Object
(
[date] => 1999-12-01 00:00:00.000000
)
[cartNumberHolder] => 0
[datecreated] => DateTime Object
(
[date] => 2017-08-30 14:51:25.000000
)
[dateupdate] => DateTime Object
(
[date] => 2017-08-30 16:36:18.000000
)
[status] => 2
)
[userId] => 16
)
)
How can I get the first result from the createQuery method?
Is Yii1 has any native methods to get the raw SQL with variables built?
I try to get a complex query built on a few subqueries using CDbExpression and CommandBuilder. I got this as a result:
SELECT * FROM `news` `t` WHERE id IN (:ycp0, :ycp1, :ycp2, :ycp3, :ycp4) LIMIT 5
The dump of the criteria content:
CDbCriteria Object (
[select] => *
[condition] => id IN (:ycp0, :ycp1, :ycp2, :ycp3, :ycp4)
...
[params] => Array(
[:ycp0] => CDbExpression Object(
[expression] => SELECT id FROM `news` `t` WHERE (rubric=:rb1) AND (:im2 & `im`=:im2) LIMIT 1
[params] => Array(
[:rb1] => 1
[:im2] => 2
)
)
...
)
)
I expected for compiled query string like this:
SELECT * FROM .. WHERE id IN(
(SELECT id FROM .. WHERE .. ORDER BY .. LIMIT 1),
(SELECT id FROM .. WHERE .. ORDER BY .. LIMIT 1)
) ORDER BY .. LIMIT 5
This is what I do in my code
$criteria = new CDbCriteria( ... );
$sql = $this->commandBuilder->createFindCommand($tableName, $criteria)->getText();
$queries[] = new CDbExpression($sql, $criteria->params);
Then I try to combine subqueries to one complex query
$criteria = new CDbCriteria( ... );
$criteria->addInCondition('id', $queries);
And finally, I try to get the result as SQL-query
$sql = $this->commandBuilder->createFindCommand($tableName, $criteria)->getText();
You get the SQL with params, as you have
$sql = $this->commandBuilder->createFindCommand($tableName, $criteria)->getText();
Then get the params enclosed in quotes:
$params = array_map(function($param) { return '"' . $param . '"'; }, $criteria->params);
Finally, replace the pairs:
echo strtr($sql, $params);
You can use enableParamLogging in your db config (boolean). You can set it up so it's used conditionally -- make sure to not use it in production.
'db' => [
'connectionString' => 'mysql:host=' . $dbhost . ';port=' . $dbport . ';dbname=' . $dbname,
'emulatePrepare' => true,
'username' => $db_user,
'password' => $db_pass,
'schemaCachingDuration' => 3600,
'charset' => 'utf8',
'enableProfiling' => $db_profile,
'enableParamLogging' => $db_params,
],
Then you can add 'class'=>'CWebLogRoute' to your log routes if you want to see all the output in your browser. docs
I think you want to do something like this:
$criteria = ...;
$command = $builder->createFindCommand($schema->getTable('name_of_table'), $criteria);
$results = $command->text;
There are few other options to perform the same thing but i will suggest you
should use the following
$results = MyModel::model()->findAllBySql("...");
Or you can prefer the following :
Sub-queries ActiveRecord Yii
This query kills the whole page (90% of the request time):
/**
* Checks if a conversation exists containing these users (at least two!)
* //TODO: fixme! SUPER-SLOW! 5s on a 6s page load total
*
* #param array $users Users to check on
* #param int $limit Limit - needs at least 2 users
* #return array Results
*/
public function partOfConversations($users, $limit = 5) {
$options = array(
'conditions' => array('ConversationUser.status <' => ConversationUser::STATUS_REMOVED),
'group' => array('ConversationUser.conversation_id HAVING SUM(CASE WHEN ConversationUser.`user_id` in (\'' . implode('\', \'', $users) . '\') THEN 1 ELSE 0 END) = ' . count($users) . ''),
'contain' => array('Conversation' => array('LastMessage')),
'limit' => $limit,
'order' => array('Conversation.last_message_id' => 'DESC')
);
return $this->ConversationUser->find('all', $options);
}
The resulting query is
SELECT `ConversationUser`.`id`, `ConversationUser`.`conversation_id`,
`ConversationUser`.`user_id`, `ConversationUser`.`status`, `ConversationUser`.`created`,
`Conversation`.`id`, `Conversation`.`user_id`, `Conversation`.`title`,
`Conversation`.`created`, `Conversation`.`last_message_id`, `Conversation`.`count`
FROM `comm_conversation_users` AS `ConversationUser`
LEFT JOIN `comm_conversations` AS `Conversation`
ON (`ConversationUser`.`conversation_id` = `Conversation`.`id`)
WHERE `ConversationUser`.`status` < 7 GROUP BY `ConversationUser`.`conversation_id`
HAVING SUM(CASE WHEN `ConversationUser`.`user_id` in
('2ed23d7c-dcc8-4d3b-8e7b-0fe018b0f9bf', '297e0fcc-8880-4bc7-9b57-0ba418b0f9bf')
THEN 1 ELSE 0 END) = 2
ORDER BY `Conversation`.`last_message_id` DESC
LIMIT 5
What it tries to do is to find out whether in a 1..x conversation two or more users are part of it (passed as $users).
Is there any way to speed that up?
Conversation 1:N ConversationUser N:1 User
Records are not too many: 70k Conversation, 130k ConversationUser
The fact that this also uses UUIds instead of normal AIID integers is probably making it worse.
But it should still not be 5s.
Besides ensuring your sql tables are optimized via indexes for that query, I think you should add another condition- only those records with acceptable user_id's.
Here is the appropriate WHERE clause
WHERE `ConversationUser`.`status` < 7
AND `ConversationUser`.`user_id` in
('2ed23d7c-dcc8-4d3b-8e7b-0fe018b0f9bf', '297e0fcc-8880-4bc7-9b57-0ba418b0f9bf')
Changing the PHP code to:
public function partOfConversations($users, $limit = 5) {
$options = array(
'conditions' => array('ConversationUser.status <' => ConversationUser::STATUS_REMOVED
,'ConversationUser.user_id' => $users),
'group' => array('ConversationUser.conversation_id HAVING SUM(CASE WHEN ConversationUser.`user_id` in (\'' . implode('\', \'', $users) . '\') THEN 1 ELSE 0 END) = ' . count($users) . ''),
'contain' => array('Conversation' => array('LastMessage')),
'limit' => $limit,
'order' => array('Conversation.last_message_id' => 'DESC')
);
return $this->ConversationUser->find('all', $options);
}
My array print_r is :
Array
(
[email] => xxx#cs.caddmu.edu
[attempt] => 0
[timestamp] => 1369676665
[smtp-id] => <1369676650.51a39b6a76cec#www.openaccesspub.org>
[response] => 451 4.2.0 Temporarily Grey listed. Try again in a couple of minutes
[category] => Invitation
[event] => deferred
)
Array
(
[email] => reidsdds#cs.cdsmu.edu
[timestamp] => 1369676845
[smtp-id] => <1369676650.51a39b6a76cec#www.openaccesspub.org>
[response] => 250 2.0.0 r4RHlOGH017661 Message accepted for delivery
[category] => Invitation
[event] => delivered
)
Array
(
[email] => jrai#openhh.com
[timestamp] => 1369678994
[smtp-id] => <1369678990.51a3a48e93428#ohhpb.org>
[category] => Reviewers
[event] => processed
)
Array
(
[email] => sss#lusst.fi
[timestamp] => 1369678997
[smtp-id] => <1369678990.51a3a48e93428#oub.org>
[response] => 250 2.0.0 Ok: queued as 02C103F0454
[category] => Revie
[event] => delivered
)
And the tables have these rows :
event_id, event, email, category, timestamp, response, attempt, url, status, reason, type, action, m_id .
I'm trying to insert in mysql table with this :-
foreach ($temp_array as $key => $poke)
{
mysql_query ("INSERT INTO temp_array (email,timestamp,category,event,response,attempt,reason,o_id,operator,action,...)VALUES ('$poke[email]','$poke[timestamp]','$poke[category]','$poke[event]',.... )" );
}
But i'm getting error " Undefined index: category in
C:\xampp\htdocs\eembeta\array_temp.php on line 34
How to insert data which does not have specific sequence?
This is not about sequence, but $poke['category'] does not exist in that array (element to insert). Be sure that all array fields you want to use are initialised:
$poke['category'] = $poke['category'] ? $poke['category'] : '';
That code means: Is that field set? yes: use it. no: use empty string.
That way $poke['category'] is known, so you get no error.
Btw, you can replace '' by 0, null or whatever you need.
Before using the data inside your query, sanatize it to avoid SQL Injections. To achieve this, consider using PDO.
Answering your question
For each key, create a temporary variable like:
$event = isset($_GET ['event']) ?$_GET ['event'] : null;