Mysql CASE statement usage with Zend - mysql

I have the following query that selects some records from the database:
$select_person = $this->select()
->setIntegrityCheck(false)
->from(array('a' => 'tableA'),
array(new Zend_Db_Expr('SQL_CALC_FOUND_ROWS a.id'),
'a.cid',
'a.email',
'final' => new Zend_Db_Expr( "concat( '<div
style=\"color:#1569C7; font-weight:bold\">',
a.head , ' ' , a.tail, '</div>')" ),
'a.red_flag'
)
)
->joinLeft(array('b' => 'tableb'), ... blah blah)
->where('blah blah')
->order('a.head ASC')
I want to modify the above query so that it selects a different value for 'final' depending on the value of
a.red_flag.
which can have values - true or false.
I understand I can use the CASE statement of mysql - eg something like the following:
'final' => new Zend_Db_Expr("CASE a.red_flag WHEN 'true' THEN '$concatstr1'
ELSE '$concatstr2' END")
The value of $concatstr1 = "concat( '<div style=\"color:red; font-weight:bold\">', a.head , ' ' , a.tail, '</div>')" ;
The value of $concatstr2 = "concat( '<div style=\"color:blue; font-weight:bold\">', a.head , ' ' , a.tail, '</div>')" ;
However, it throws an error saying
Message: SQLSTATE[42000]: Syntax error or access violation: 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 'div
style="color:red; font-weight:bold">',
a.head , ' ' , ' at line 1
How can I make this query work?
Any help is greatly appreciated.
Thanks

Personnaly, I don't like to get HTML as an answer from the DB. It gets confusing and harder to debug and change afterwards. Furthermore, you might get some errors due to the confusion with the ' and " and all the reserved characters in MySQL (<, >, ;, ...) I would suggest that you try this:
'final' => new Zend_Db_Expr("CASE a.red_flag WHEN 'true' THEN 1
ELSE 0 END")
Then do a check on the value of a.red_flag;
if($this->final) {
$output .= '<div style=\"color:red; font-weight:bold\">';
} else {
$output .= '<div style=\"color:blue; font-weight:bold\">';
}
$output .= $this->head.' '.$this->tail;
$output .= '</div>';
If the query still doesn't work. Try
echo $select->__toString; exit();
and check the query. Try the output that you got with the __toString on your database and check if it works. It's easier to fix it that way. You could also show the query string here and it'll be easier to debug.

Finally, I found the error in my statement.
The culprit was - I was using quotes in $concatstr1 and $concatstr2 inside the $select_person statement.
The correct query should be formed as follows:
$select_person = $this->select()
->setIntegrityCheck(false)
->from(array('a' => 'tableA'),
array(new Zend_Db_Expr('SQL_CALC_FOUND_ROWS a.id'),
'a.cid',
'a.email',
final' => new Zend_Db_Expr("CASE a.red_flag WHEN 'true' THEN $concatstr1 ELSE $concatstr2 END"),
'a.red_flag'
)
)
->joinLeft(array('b' => 'tableb'), ... blah blah)
->where('blah blah')
->order('a.head ASC');
This is now returning me the appropriate value of 'final' - concatstr1 when red_flag is true otherwise it is returning me concatstr2.

Related

UTF-8 Bad Encoding when Using ZF2 dbAdapter for mySQL for Update

I am getting the Exception when I attempt to update the record with "tableGateway" object:
Zend\Db\Adapter\Exception\InvalidQueryException
Statement could not be executed
(HY000 - 1300 - Invalid utf8 character string: 'C`\xC3`\xB3`digo')
I have the following table structure with data in mySQL:
CREATE TABLE `clientes` (
`Código` int,
`Nome` varchar(50),
`Descricao` varchar(150)
....
);
INSERT INTO `clientes` (`Código`, `Nome`, `Descricao`)
VALUES (1, 'Test Nome', 'Test Descricao');
The database encoding is 'latin1', but the database configuration is as shown:
'mycnn' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname={$mydb};host={$myhost}',
'username' => '{$myuser}',
'password' => '{$mypassword}',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
)
As you can see the above scenario, I have setup the driver for "UTF-8", the column name "Código" has a special character and renaming this column is not an option.
The syntax that I am using for updating in the model is:
$set = array("Nome" => "Edited Test");
$where = array("Código" => 1);
$this->tableGateway->update($set, $where);
After that, the ZF is parsing the SQL throwing the Exception:
UPDATE "clientes" SET "Nome" = 'Edited Test' WHERE "C`\xC3`\xB3`digo" = 1
I have also removed the UTF-8 option, since the catalog is "latin1_swedish_ci" without success.
I would appreciate anyone who gives me a hint how to face this issue.
Thanks in advance.
Make sure your database encoding type is UTF-8.
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
Make sure fields have utf8_general_ci.
In your layout phtml head has
<meta charset='utf-8'>
Updated
As you said you are not able to change encoding to utf-8 so use one of the following commands using driver_options
'SET NAMES \'latin1\'' or 'SET CHARACTER SET \'latin1\''
For more details check out the doc please!
When problem with column name which has latin1 characters
Just pass the condition as string not an array as the second argument into TableGateway's update() method. But you must set this 'SET NAMES \'UTF8\'' in your driver_options.
$id = 1;
$where = "Código = {$id}";
// Or use this way
$where = "Código = 1";
$this->tableGateway->update($set, $where);

CakePHP 3.0: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax

I faced saving data to database using Form in CakePHP 3.0.
//add.ctp
<div>
<?= $this->Form->create($deposit) ?>
<fieldset>
<legend><?= __('Add') ?></legend>
<?php
echo $this->Form->input('date');
echo $this->Form->input('profile_id', ['options' => $profiles]);
echo $this->Form->input('amnt');
echo $this->Form->input('desc');
echo $this->Form->input('user_id', ['options' => $users]);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
Here is my add function
public function add()
{
$deposit = $this->Deposits->newEntity();
if ($this->request->is('post')) {
$deposit = $this->Deposits->patchEntity($deposit, $this->request->data);
if ($this->Deposits->save($deposit)) {
$this->Flash->success(__('The member deposit has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The member deposit could not be saved. Please, try again.'));
}
}
$profiles = $this->Deposits->Profiles->find('list', ['limit' => 200]);
$users = $this->Deposits->Users->find('list', ['limit' => 200]);
$this->set(compact('deposit', 'profiles', 'users'));
}
When i submitted the the Form i found below Database syntex Error
Error: SQLSTATE[42000]: Syntax error or access violation: 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 'desc, user_id, created, modified) VALUES ('2015-06-06', 7, '3211', 'some text', 1,' at line 1
And SQL Query was showing:
INSERT INTO member_deposits (date, profile_id, amnt, desc, user_id, created, modified) VALUES (:c0, :c1, :c2, :c3, :c4, :c5, :c6)
I spent plenty of time resolving the issue by Googling and from Similar Post, no luck, but after spending a day i found to get resolve simply configuring quoteIdentifiers to true.
quoteIdentifiers is by default set to false at config/app.php under Datasources of your cake project.
One of your columns is using a column name that is reserved by MySQL.
dev.mysql.com/doc/refman/5.0/en/reserved-words.html
As you can see, DESC is reserved.
If you can find a way to change the query to use escaped column name specifies, mysql will tolerate this. for example
INSERT INTO `member_deposits` (
`date`, `profile_id`, `amnt`,
`desc`, `user_id`, `created`, `modified`)
VALUES (:c0, :c1, :c2, :c3, :c4, :c5, :c6)
Alternatively, change the column name to something that does not violate the mysql reserved word rule.

Using PDO to insert variables into SELECT clause?

I am attempting to get the distance from a user to each venue stored in a MySQL database, using the spherical law of cosines. The user inputs their location, and the following query is executed.
$data = array(':lat' => $lat, ':lon' => $lon);
$qry = "SELECT ACOS(SIN(v.Latitude) * SIN(:lat) + COS(v.Latitude) * COS(:lat) * COS(:lon - v.Longitude)) * 3963 AS distance FROM Venue v";
$stmt = $pdo->prepare($qry);
$stmt->execute($data);
$rows = $stmt->fetchAll();
The problem is, I get the following error.
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY093]: Invalid parameter number'
When I remove the variables (:lat and :lon) from the SELECT clause, it works just fine. Other variables further on in the statement (not shown here) work just fine, it is only the variables in the SELECT clause that cause an issue. Is this inability to use PDO variables within SELECT clauses a limitation of PDO, or is there a way around this issue?
I am using PHP 5.4.15, and my PDO options are as follows.
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', // UTF-8 to prevent issue sending special characters with JSON
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // fire exceptions for errors (turn this off for release)
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // only return results indexed by column name
PDO::ATTR_EMULATE_PREPARES => false // actually prepare statements, not pseudo-prepare ( http://stackoverflow.com/questions/10113562/pdo-mysql-use-pdoattr-emulate-prepares-or-not )
);
$data = array($lat, $lat, $lon);
$qry = "SELECT ACOS(SIN(v.Latitude) * SIN(?) + COS(v.Latitude) * COS(?) * COS(? - v.Longitude)) * 3963 AS distance FROM Venue v";
$stmt = $pdo->prepare($qry);
$stmt->execute($data);
$rows = $stmt->fetchAll();

Codeigniter database issue

Having a spot of bother trying to grab some data out of my database.
I have the following model:
function GetRestaurants($options = array())
{
// Qualification
if(isset($options['restaurantID']))
$this->db->where('restaurantID', $options['restaurantID']);
if(isset($options['restaurantRegionID']))
$this->db->where('restaurantRegionID', $options['restaurantRegionID']);
if(isset($options['restaurantName']))
$this->db->where('restaurantName', $options['restaurantName']);
if(isset($options['restaurantAddress1']))
$this->db->where('restaurantAddress1', $options['restaurantAddress1']);
if(isset($options['restaurantAddress2']))
$this->db->where('restaurantAddress2', $options['restaurantAddress2']);
if(isset($options['restaurantSuburb']))
$this->db->where('restaurantSuburb', $options['restaurantSuburb']);
if(isset($options['restaurantCity']))
$this->db->where('restaurantCity', $options['restaurantCity']);
if(isset($options['restaurantInformation']))
$this->db->where('restaurantInformation', $options['restaurantInformation']);
// limit / offset
if(isset($options['limit']) && isset($options['offset']))
$this->db->limit($options['limit'], $options['offset']);
else if(isset($options['limit']))
$this->db->limit($options['limit']);
// sort
if(isset($options['sortBy']) && isset($options['sortDirection']))
$this->db->order_by($options['sortBy'], $options['sortDirection']);
$query = $this->db->get("tblRestaurants");
if(isset($options['count'])) return $query->num_rows();
if(isset($options['restaurantID']))
return $query->row(0);
if(isset($options['limit']) && $options['limit'] == '1')
return $query->row(0);
return $query->result();
}
Now the following code works fine:
$this->load->model('Restaurants_model');
$data['restaurant'] = $this->Restaurants_model->GetRestaurants(array(
'restaurantName' => 'shed 5',
'limit' => '1'
));
However the following does not work:
$this->load->model('Restaurants_model');
$data['restaurant'] = $this->Restaurants_model->GetRestaurants(array(
'restaurantName' => str_replace('-', ' ', $this->uri->segment(2)),
'limit' => '1'
));
Even though the result of
str_replace('-', ' ', $this->uri->segment(2))
is in this instance: ‘shed 5’.
I have compared var_dumps of the output of the str_replace and the string itself and determined them to be identical. So why does the straight string return a result yet the string generated from the uri segment doesn’t? Some kind of encoding issue? My database holds data in ‘utf8_general_ci’.
Thanks for any suggestions!
$restaurant=str_replace('-', ' ', $this->uri->segment(2));
get value outside array and try array_push
$data['restaurant'] = $this->Restaurants_model->GetRestaurants(array(
'restaurantName' => $restaurant,
'limit' => '1'
));

PGError syntax problem for named_scope

I have the following named_scope which works fine in MySQL and sqlite but bombs in Postgres:
course.rb
named_scope :current, :conditions => ['start < ? AND end > ? ', Time.now, Time.now], :order => 'start ASC'
Then I just call:
Course.current
I get the error:
PGError: ERROR: syntax error at or
near "end" LINE 1: ... WHERE (start <
'2010-03-17 14:03:24.995746' AND end >
'201...
^ : SELECT count(*) AS count_all FROM
"courses" WHERE (start <
'2010-03-17 14:03:24.995746' AND end >
'2010-03-17 14:03:24.995748' )
My google-fu is failing me so I'm hoping Stack Overflow won't. Any ideas on how to make that scope Postgres-friendly? Thanks,
Drew
END is a keyword, you have to use another name or place it between double quotes "end".
If you use double quotes around the columnname and use this code also for MySQL, tell MySQL to accept double quotes as object identifier by setting the correct SQL MODE: ANSI_QUOTES