So this is odd and hopefully there is a simple answer. I have a SQL query that used a date as the first parameter in a where() clause. But for some reason CodeIginter appears to be trying to add in extra escape characters,
Here is my code
$this->db->select("*");
$this->db->from("equip_reserve");
$this->db->where('equip_list_id = '.$equip_list_id);
$this->db->where('"'. date("Y-m-d H:i",strtotime($startdate)) .'" between date and returndate');
Here is the result:
SELECT * FROM 'equip_reserve' WHERE 'equip_list_id' = 5 AND "2016-02-29 '14:20'" between 'date' and 'returndate'
As you can see the date after the AND clause is causing this statement to fail.
Any suggestions on how to fix it?
I ended up fixing it by just passing the SQL directly to CodeIgniter instead of using their helper functions. In case anyone ever has this problem.
$st = date("Y-m-d H:i",strtotime($startdate));
$sql = "SELECT * FROM `equip_reserve` WHERE ? between `date` AND `returndate` and `equip_list_id` = ?";
$query = $this->db->query(
$sql,
array($star,$equip_list_id)
);
return $query->result();
Fixed!
Related
I have fields id and date defined as VARCHAR(16)
When I do this query:
SELECT *
FROM `members`
WHERE `id` = '4412040999876'
AND `date` = '201706054783'
I get no results.
When I do it like this:
SELECT *
FROM `members`
WHERE `id` = 4412040999876
AND `date` = 201706054783
Note - without the quotes - I get the result I am expecting.
EDIT: Here is the code used - I am not manually adding quotes. CI's DB class is adding them.
public function get_member_match($id, $mem, $field = 'name')
{
$sql = "
SELECT *
FROM `members`
WHERE `id` = ?
AND `" . $field . "` = ?
";
$sql_array = array($id, $mem);
$q = $this->db->query($sql, $sql_array);
return $q->result_array();
}
And I call this function as:
$this->members_model->get_member_match($id, $date, 'date');
I output the query, and the variables are matched correctly, no errors, only the quotes.
Any idea why? I never had this problem before. Working on CodeIgniter 3 using Query Builder.
EDIT2: Summary of findings so far:
Localhost (MySQL 5.6.24) works, server (MySQL 5.5.55-0+deb7u1) doesn't.
The problem occurs in my code and in PHPMyAdmin on the server but works locally, so I eliminate a code issue.
The show variables like 'char%' query shows all character set settings identical on local and on the server.
Database and fields have the same encoding on both server and local.
Does not seem to be a casting issue as many of the comments suggest, as the problem is not present on localhost, only on the server, unless the server has config or other issues.
...?
id might be defined as integer in your database. To match against integer fields you do not need to use quotes. Quotes are used when you match against string or text fields.
This should cast it back from the codeigniter's auto cast:
SELECT *
FROM `members`
WHERE `id` = '4412040999876'
AND `date` = '201706054783'
SELECT *
FROM `members`
WHERE CAST(`id` as INTEGER) = '4412040999876'
AND `date` = '201706054783'
Try to use this
$this->db->from('members');
$this->db->where('id',$id);
$this->db->where($field,$mem);
$q = $this->db->get();
return $q->result_array();
It's because the quotes imply that it is a string, whereas id field is an integer and must be written without quotes.
Same for date. Internally date is stored as an integer but is able to convert string into dates as long as they have an appropriate format
So basically I have a TIMESTAMPDIFF query in my model to determine the duration and I want it to display the duration in a view. The problem is, it will display the error.
Please help me, thank you.
Here's my query of my model (model_attendance.php):
public function getOne($username){
$sql = "SELECT empnum FROM employees WHERE username='$username'";
$result = $this->db->query($sql);
$sql1 = "SELECT a.empnum,CONCAT(a.name,' ',a.midname,' ',a.lastname) AS
NAME,CONCAT(b.indate,' ',b.intime) AS 'TIMEIN',CONCAT(b.outdate,'
',b.outtime)AS 'TIMEOUT', TIMESTAMPDIFF(HOUR, 'TIMEIN','TIMEOUT') AS 'DUR'
FROM employees AS a
JOIN times AS b ON (a.empnum=b.userid)
WHERE b.indate BETWEEN
DATE(CONCAT(YEAR(CURRENT_TIMESTAMP),'-',MONTH(CURRENT_TIMESTAMP),'-','01'))
AND DATE(LAST_DAY(CURRENT_TIMESTAMP)) AND b.userid='".$result->row(0)->empnum."'";
$query = $this->db->query($sql1);
return $query->result();
}
To solve this problem, you need to Pass return type as "false" to Active record select query.
$this->db->select("TIMESTAMPDIFF(YEAR,a.date_birth, CURDATE()) AS age", false);
Assign that to variable and pass that to your SQL Query.
$now = date('Y-m-d H:i:s'); # 2015-1-30 04:32:25 / With time
$now = date('Y-m-d'); # 2015-1-30 / Without time
Its potentially a bug. I Havent checked the Query Builder class yet. But to fix this...you can try by adding ` to the column like this
$this->db->select("TIMESTAMPDIFF(YEAR, `a.date_birth`, CURDATE()) AS age");
or
$this->db->query("TIMESTAMPDIFF(YEAR, `a.date_birth`, CURDATE()) AS age");
I know my question is similar to other question already answered but my issue is different because I need some alternative or advice no how to go the other way around.
My issue is: I want to get values between either two dates or one according to what user wants..
When User request data of one day.. php query data successful.. but problem is when data requested is between two dates..
$query = $this->db->query("SELECT * FROM `meta_receipt_data`
WHERE `meta_transaction_date` >= '$first_date' AND
`meta_transaction_date` <= '$second_date' ");
return $query->result();
I get an empty set...
So I thought may be the values are not submitted correct.. so I echoed the values to see if they are correct or not. I find they are correct...
$first_date = 09/13/2014;
$second_date = 09/19/2014;
But if I try to put the value like
$query = $this->db->query("SELECT * FROM `meta_receipt_data`
WHERE `meta_transaction_date` >= '09/13/2014' AND
`meta_transaction_date` <= '09/19/2014' ");
return $query->result();
I get my result back correct.. so is there anything am doing it wrong??
Change the type of meta_transaction_date to DATE as that is what it is! Also use the standard 'yyyy-mm-dd' when passing in DATEs.
Your problem probably stems from string ordering of the 'mm/dd/yyyy' US date format which is horrible for coding. If you wish to display the DATE in this format, convert it when SELECTing the final output.
MySQL has a built in function called Between that you can use like this:
SELECT * FROM table_name WHERE date_column BETWEEN 'start_date_parameter' AND 'end_time_parameter'
Try to cast the date first , and then with between statement:
$query = $this->db->query("SELECT * FROM `meta_receipt_data`
WHERE `meta_transaction_date` BETWEEN
date_format(str_to_date('$first_date', '%d/%m/%Y'), '%Y-%m-%d') AND
date_format(str_to_date('$second_date', '%d/%m/%Y'), '%Y-%m-%d')");
$query = $this->db->query("SELECT * FROM `meta_receipt_data`
WHERE `meta_transaction_date` >= '09/13/2014'
AND `meta_transaction_date` <= '09/19/2014' ");
Since the above seems to be working fine, the problem is in your code.
$query = $this->db->query("SELECT `meta_transaction_date` FROM meta_receipt_data WHERE
meta_transaction_date BETWEEN "
.date( "Y-M-d", ( strtotime($first_date) ) )." AND "
.date( "Y-M-d", ( strtotime($second_date) ) ) );
A word of advice, do not use queries like SELECT * as they will degrade performance of your application. And I just read in your comment to your own question:
I have set the type as Varchar
Do not do that. It is best to use the DATE type to store dates. You can use the query:
ALTER TABLE `meta_receipt_data`
MODIFY `meta_transaction_date` DATE NOT NULL;`
Well, that is assuming you wish to keep the column to not accept null values.
I found that the value had space before and after so I use $first = trim($first_date); and problem solved...
I have a mysql datetime field that stores dates in the form '2013-12-25 00:00:00'
I need to select all records for any month in the table with a query like:
$sql = "SELECT *
FROM `images`
WHERE (photodate BETWEEN '2003-11-01 00:00:00' AND '2003-12-03 00:00:00')
ORDER BY photodate DESC
LIMIT 30";
The above select query does the job fine.
In order to change the dates, I need to replace the '2003-11-01 00:00:00'AND'2003-12-03 00:00:00' with variables, so I set a variable with input data from two drop down lists for $startyear and $startmonth and convert it to what I think is the correct form using:
$startdate = $startyear."-".$startmonth."-01 00:00:00";
I do the same to the $enddate by adding 1 to the $startmonth.
My code then becomes:
$sql = "SELECT *
FROM `images`
WHERE (photodate BETWEEN $startdate AND $enddate)
ORDER BY photodate DESC
LIMIT 30";
This does not work at all and gives a MySQL error. Having struggled with it for a month and finding nothing on any forum that uses variables instead of text, I am totally at a loss as to how it could be done. All help appreciated.
You are vulnerable to SQL injection attacks, which is why it's not working. You're producing the literal query
... WHERE (photodate BETWEEN 2003-11-01 00:00:00 AND 2013-12-03 00:00:00)
The 2003-11-01 and 2013-12-03 will be interpreted as a series of mathematical subtractions, and the 00:00:00 will be a simple flat-out syntax error. You need to, at bare minimum, quote those values:
... WHERE (photodate BETWEEN '$startdate' AND '$enddate')
^----------^-----^--------^--- note the quotes
so that mysql can see the WHOLE date as a date value, and not some arbitrary broken strings.
I guess you're missing some apostrophes... try this:
$sql = "SELECT * FROM images WHERE (photodate BETWEEN '$startdate' AND '$enddate') ORDER BY photodate DESC LIMIT 30";
You could have problems with the logic. In $enddate doesn't adding 1 to the start month give you 13?
Try printing out the contents $sql when the variables are in and see how it compares to the working $sql.
Please add apostrophes your query (and sanitize your variables using mysql_real_escape_string, PDO bind values, mysqli_real_escape_string) :
$sql = 'SELECT * FROM 'images' WHERE (photodate BETWEEN '.$startdate.' AND '.$enddate.') ORDER BY photodate DESC LIMIT 30';
A little reminder, you shall NOT use MySQL (deprecated, old.. and not that fast), if you're using MySQLi or going to use it, please sanitize your variables like this, as Marc B said it could break your script and your app security :
<?php
// Starting MySQLi Connection
$db = mysqli_connect("host", "user", "password", "dbname");
// Sanitizing your variables
$startdate = mysqli_real_escape_string($db, $startdate);
$enddate = mysqli_real_escape_string($db, $enddate);
// Query
$sql = "SELECT * FROM 'images' WHERE (photodate BETWEEN ".$startdate." AND ".$enddate.") ORDER BY photodate DESC LIMIT 30";
// Doing the query and print the result array
$var = mysqli_query($db, $sql);
print_r($var);
// Closing connection
mysqli_close($db);
?>
Please refer to to this for PDO way or to this for MySQLi way, you can also check the MySQL_real_escape_string into PHP doc but MySQL functions are deprecated since PHP 5.5
I've got a table with some columns. I want to filter some records using two of them, the one with INT type and second with DATETIME type. I'm using PHP PDO extension to connect with database and make some queries.
I'm trying to get the records from my table where datetime field is lower then given date, f.e.
<?php
$date = date("Y-m-d");
$this->db->query("SELECT * FROM `" . DB_PREFIX . "fanpage` WHERE `flag_warning` = ? AND DATE(`update_date`) < ?", array(1, $date));
?>
This returns NULL, but when I paste the same query into the phpMyAdmin window it shows me proper records. What is the problem?
Edit:
Fragment from query function:
public function query($sql, $params = array())
{
$result = array();
$result['query'] = $this->pdo->prepare($sql);
$result['query']->execute($params);
$this->lastResult = $result['query'];
unset($result['query']);
}
No need for the prepared statements at all
WHERE flag_warning = 1 AND update_date < CURDATE()
Use
$sqlStatement = $this->db->prepare("SELECT * FROM `" . DB_PREFIX . "fanpage` WHERE `flag_warning` = ? AND `update_date` < CURDATE()");
$this->db->execute(array(1));
$result = $sqlStatement->fetchAll(PDO::FETCH_ASSOC);
Now $result has what you need.
I've changed the column name to date_time_upd and it works right now, I think it's bug or something, maybe someone can explain that?
Edit:
Okay, I've figured it out. There was a fragment of code that checked for occurrence of the "UPDATE, DELETE OR INSERT" word in the query, and if there was a word like that the query result was not fetched. I've changed that to search for SELECT word, now everything is okay.