Sql string query not working - php

I'm building some Sql queries in Yii framework.
So far all is working fine up until I need to compare a variable to a string.
Here is my function with the query:
public function countCanceled()
{
$week = Person_Event::model()->weekByDate();
$week_id = $week->id;
$datalogin = mysqli_connect( /*connect is working fine*/);
$sql = "SELECT id FROM tbl_event WHERE week_id=$week_id AND status_id='canceled'";
$query = mysqli_query($datalogin, $sql);
$numrows = mysqli_num_rows($query);
return $numrows;
}
Now , I clearly have one event with canceled status, and I ran the same query in MySql server and the result of 1 was given, so why in Yii it doesn't work?
(tried to switch "=" with "like" , made no difference)
p.s Yes , in this particular case I could use the built in Yii's queries , but I have other, much more complicated queries where I need to compare string.
Thanks,
Mark.

What is type of status_id if is char then data is space padded to full length. You can change it to varchar and then compare. And for like you can use LIKE 'canceled%'
ps. sorry I not have enough reputation to comment...:(
Best regards,
Nebojsa

Related

PHP SQL Request: select only the lowest value of time where name = $name and stage = $stage

Hi so I've already got a php script working working for this but it use a massive amount of data for a really easy task so I really would like to improve it.
My problem is the following: I have a SQL database build like this
and I would to do request like this one:
http://myphppage.php?username=Whataname&stage=1
and I would like it to echo the result so that if I read my php page content I can read the following:
21
so basicly all I want is to do a request with the username and the stage as parameters and I would like it to return the lowest value of the column "time" WHERE name=the name parameter entered AND stage = the stage parameter entered
I'm not really good in sql but I'm pretty I can make this kind of sql request in a single line or two instead of this massive script I have right now.
here's the current script I have:
<?php
$q2 = "SELECT username FROM DB WHERE stage='$stage' GROUP BY username ORDER BY time ASC";
$result2 = mysql_query($q2);
$times = array();
$userusernames = array();
$usernames = mysql_fetch_assoc($result2);
while($rows=mysql_fetch_assoc($result2))
{
$temp = $rows['username'];
$q3 = "SELECT time FROM DB WHERE stage='$stage' AND username='$temp' GROUP BY time ORDER BY time ASC";
$result3 = mysql_query($q3);
while($aaa = mysql_fetch_assoc($result3))
{
array_push($times, $aaa['time']);
array_push($userusernames, $rows['username']);
if($rows['username']==$username)
{
echo $aaa['time'];
}
break;
}
}
?>
may someone please help me figuring out how to do this
EDIT: I have been looking around on internet but I can't find what I'm looking for, I'm pretty sure there's the answer somewhere so maybe you can just help me reformulate my question and I could find the answer by myself. I'm pretty stuck due to my lack of english vocabulary...
thx in advance
You can archive the wanted result with only one query:
SELECT username, MIN(time) AS lowertime
FROM test_table
WHERE stage='$stage' AND username='$temp'
GROUP BY username
ORDER BY time

Update Oracle CLOB with PHP

I have an Oracle table with 1 field of datatype CLOB.
I want to replace the contents of the CLOB with a long string (over 4,000 characters).
Is OCI8 the easiest way to do this using PHP?
Regular sql would be simply something like this:
Update TableX
Set clobFieldX = 'my very long string'
Where keyField = 'value';
I've been googling for a simple example but can't find one that updates the CLOB with a 'where something = something' clause.
http://php.net/manual/en/function.oci-new-descriptor.php has an example of an insert statement. I'll try it in a bit, but it is as simple as changing the insert example to an update example?
Side note: is OCI the best way to interact with Oracle with PHP? Is there is a friendlier library/extension?
This worked: function updateClob($groupId,$memberList,$conn) {
$sql = "UPDATE LP_GROUP SET MEMBER_EXPR_XML = EMPTY_CLOB() WHERE GROUP_ID = '$groupId' RETURNING MEMBER_EXPR_XML INTO :lob";
//echo $sql."\n";
$clob = OCINewDescriptor($conn, OCI_D_LOB);
$stmt = OCIParse($conn, $sql);
OCIBindByName($stmt, ':lob', &$clob, -1, OCI_B_CLOB);
OCIExecute($stmt,OCI_DEFAULT);
if($clob->save($memberList)){
OCICommit($conn);
echo $groupId." Updated"."\n";
}else{
echo $groupId." Problems: Couldn't upload Clob. This usually means the where condition had no match \n";
}
$clob->free();
OCIFreeStatement($stmt);
}

MySQL query that can handle missing characters

I'm trying to improve my MySQL query.
SELECT gamename
FROM giveaway
WHERE gamename LIKE '$query'
I got an input that consists of URL's that are formed like:
http://www.steamgifts.com/giveaway/l7Jlj/plain-sight
http://www.steamgifts.com/giveaway/okjzc/tex-murphy-martian-memorandum
http://www.steamgifts.com/giveaway/RqIqD/flyn
http://www.steamgifts.com/giveaway/FzJBC/penguins-arena-sednas-world
I take the game name from the URL and use this as input for a SQL query.
$query = "plain sight"
$query = "tex murphy martian memorandum"
$query = "flyn"
$query = "penguins arena sednas world"
Now in the database the matching name sometimes has more characters like : ' !, etc.
Example:
"Plain Sight"
"Tex Murphy: Martian Memorandum"
"Fly'N"
"Penguins Arena: Sedna's World!"
So when putting in the acquired name from the URL this doesn't produce results for the 2nd, 3rd and 4th example.
So what I did was use a % character.
$query = "plain%sight"
$query = "tex%murphy%martian%memorandum"
$query = "flyn"
$query = "penguins%arena%sednas%world"
This now gives result on the 1st and 2nd example.
.
On to my question:
My question is, how to better improve this so that also the 3rd and 4th ones work?
I'm thinking about adding extra % before and after each character:
$query = "%f%l%y%n%"
$query = "%p%e%n%g%u%i%n%s%a%r%e%n%a%s%e%d%n%a%s%w%o%r%l%d%"
But I'm not sure how that would go performance wise and if this is the best solution for it.
Is adding % a good solution?
Any other tips on how to make a good working query?
Progress:
After a bit of testing I found that adding lots of wildcards (%) is not a good idea. You will get returned unexpected results from the database, simply because you just added a lot of ways things could match.
Using the slug method seems to be the only option.
If i get your question well, you are creating a way of searching through those informations. And if that is the case then try
$query = addslashes($query);
SELECT name
FROM giveaway
WHERE gamename LIKE '%$query%'
Now if you want to enlarge your search and search for every single word that looks like the words in your string, then you can explode the text and search for each word by doing
<?php
$query = addslashes($query);
//We explode the query into a table
$tableau=explode(' ',$query);
$compter_tableau=count($tableau);
//We prepare the query
$req_search = "SELECT name FROM giveaway WHERE ";
//we add the percentage sign and the combine each query
for ($i = 0; $i < $compter_tableau; $i++)
{
$notremotchercher=$tableau["$i"];
if($i==$compter_tableau) { $liaison="AND"; } else { $liaison=""; }
if($i!=0) { $debutliaison="AND"; } else { $debutliaison=""; }
$req_search .= "$debutliaison gamename LIKE '%$notremotchercher%' $liaison ";
}
//Now you lauch your query here
$selection=mysqli_query($link, "$req_search") or die(mysqli_error($link));
?>
By so doing you would have added the % to every word in your query which will give you more result that you can choose from.

SQL query result to string

I'm using SQL in Yii framework.
I need to show the person's latest active week (it's number and date).So I wrote following code:
public function latestWeek()
{
$datalogin=//the login is working fine
$sql ="SELECT w.number,MAX(w.start_date)
FROM tbl_person_week t, tbl_week w
WHERE t.person_id=$this->id AND t.week_id=w.id";
$query = mysqli_query($datalogin, $sql);
return $query;
}
Now , I checked this query on the server and it works fine (almost) but first thing: I need to convert it into string , because yii's CgridView can't read it , and I couldn't find a working solution for this.
Second: on the server , it gave me the max date indeed , but not it's correct number , but the first number available. How can I fix this as well?
Queries like that should never be used in objective framework. If yu want to execute your own query, you should do it this way:
$sql = "your sql code";
$array = Yii::app()->db->createCommand($sql)->queryAll();
As result you will get multidimensional array with selected columns and rows
If you want to use it in grid view, you should do it this way:
$count = Yii::app()->db->createCommand($sql)->queryScalar();
$dataProvider = new CSqlDataProvider($sql, array('totalItemCount'=>$count));
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'grid-id',
'dataProvider'=> $dataProvider,
));
You can also use connection other than Yii::app()->db. Check CDbConnection class in docs.
edit: if you wanna use queries like mysql_fetch_assoc, check out also queryRow() method instead of queryAll()
Use Mysql_fetch _array
public function latestWeek()
{
$datalogin=//the login is working fine
$sql ="SELECT w.number,MAX(w.start_date)
FROM tbl_person_week t, tbl_week w
WHERE t.person_id=$this->id AND t.week_id=w.id";
$query = mysqli_query($datalogin, $sql);
while($row = mysqli_fetch_array($query)){
echo $row;
}
}
Assuming from your qu. that you want the week number and start date as one string, you have to concatenate the two columns in the sql.
You also need to specify that the week number is from the row with the maximum start date, which isn't as simple as you might first think.
I don't like injecting the person_id straight into SQL, it isn't awful in this case but is a bad habit to get into security-wise. There are binding methods available in the framework and I agree with Arek, that you should lean on the yii framework as much as possible.
To get the scalar string value, if you are insisting on using your own SQL.. I suggest the following:
$sql='
SELECT CONCAT('Week ',tw.number,' starting ',tw.start_date)
FROM tbl_week tw
JOIN (
SELECT MAX(twi.start_date) max_start_date
FROM tbl_week twi
JOIN tbl_person_week tpwi
ON tpwi.week_id = twi.id
AND tpwi.person_id = :person_id
) i
ON tw.start_date = i.max_start_date;
';
$command=Yii::app()->db->createCommand($sql);
$command->bindParam(":person_id", $this->id);
return $command->queryScalar();

Combining conditions in SQL

I am using php and sql to check user information from the database. I need to check if the username and password is correct and the account is active. I have this sql query, but it does not work. What is the method to do it?
SELECT * FROM foo WHERE (name='foo' AND password='foo') AND active=1
for me
SELECT * FROM foo WHERE (name="foo" AND password="foo") AND active=1
should be same as
SELECT * FROM foo WHERE name="foo" AND password="foo" AND active=1
the above query assumes that field active is of family type int In case its varchar or char you r query should be like this
SELECT * FROM foo WHERE name="foo" AND password="foo" AND active='1'
and the query should work and i assume you are taking care of SQL injections from php
Where you say, "When I remove AND active=1 part, it works fine. Any ideas?"
Try changing it to AND active<>1 to see if the issue lies in that field. It's possible 'active' may be null or some other value. Try outputting the value (try var_dump($var) in PHP) to see what is returned for the 'active' field. If the value is 0, a blanck string, or null, then you've isolated your problem.
The query looks correct (assuming columns name, password, and active exist in table foo), but if you're using it in PHP you might be running into trouble with the double quotes if they're inside a string you're declaring. You might need to escape them or use single quotes.
My query returns 0 row and I am sure that I have that fields in the database and typing the correct information. When I remove AND active=1 part, it works fine. Any ideas?
Yes.
The idea is very simple. Just check if a record with name='foo' and password='foo' has active=1. Then correct mistake and your data
Hint: a programmer cannot be sure when the logic says he is wrong.
First of all, use mysql_real_escape_string() or a PDO method to escape your input. You do not want people messing around in your database.
A simplified version of what I normally do is
SELECT main.id,
main.isActive,
(SELECT count(sub.id)
FROM users AS sub
WHERE sub.id = main.id
AND sub.credential = 'md5password'
LIMIT 1
) AS credentialMatches
FROM users AS main
WHERE main.identity = 'username'
Grab your result:
$result = mysql_query($sql);
$data = array();
if (false !== $result) {
while ($row = mysql_fetch_assoc($result)) {
$data[] = $row;
}
}
Handle your result:
if (count($data) < 1) {
// username not found
} else if (count($data) > 1) {
// multiple rows with the same username, bad thing
} else {
$row = $data[0]
if (false === (boolean) $row['isActive']) {
// user not active
} else if (true === (boolean) $row['credentialMatches']) {
// SUCCESS
// valid user and credential
}
}
Also note: ALWAYS store password at least as an MD5 hash like so WHERE credential = MD5('password'). Same when you are inserting: SET credential = MD5('password'). This way, when someone else will ever read you database, user passwords won't be revealed so easily.
An even better is to add an additional salt to hash, but that might be going to far for now.
You could debug your sql like this in php:
$sql = "SELECT * FROM foo WHERE (name='foo' AND password='foo') AND active=1";
$result = mysql_query($sql) or die (mysql_error());
This "or die (mysql_error())" will give you the exact error of that query, maybe the DB isn't selected if that happened use mysql?query($sql, $db)...
Hope it helps

Categories