LIKE SQL with parameters throwing Invalid Parameter Number - php

So I'm trying to use a "LIKE" in the SQL, basically to see if a player is in a team already. Here's the code I have:
$checkifonlytwo = "SELECT * FROM sg_turn_teams WHERE joinid = :joinid AND players LIKE '%:ownerid,%'";
$paramstwo = array(
":joinid" => $joinid,
":ownerid" => $_SESSION['user']['id']
);
try{
$stmttwo = $db->prepare($checkifonlytwo);
$resulttwo = $stmttwo->execute($paramstwo);
}
catch(PDOException $ex){
die("Failed to run query #2: " . $ex->getMessage());
}
Also as you can see I want it to be LIKE '%1,%' for example, so the comma at the end too.
My table structure looks like this.
EDIT, the players is going to be like "1,2,3" without the names because the users are able to change their name. The picture is with names, but it's supposed to be 1,2,3

Foreword. I decided to make this a community wiki. I did not want to gain anything from this, except for the OP and others visiting the question.
As I said in comments, you're going about it the wrong way with the comma in there ownerid,.
What you need to do is implode on the array and using IN().
Borrowed from https://stackoverflow.com/a/12151295/
$e = 0;
while($e<$num1){
$units = 0;
$r = 0;
$SO_Line_Item=mysql_result($result1,$e,"SO_Line_Item");
foreach ($Boxes[$e] as $a => $b)
{
$zzz[] = $Boxes[$e][$r];
$ce = count($Boxes[$e]);
$r++;
}
//end inner foreach
$products = implode(',', array_fill(0,$ce, '?'));
$db = new PDO('mysql:host=192.168.1.197 ;dbname=Tracking', $dbuser,$dbpass);
$stmt = $db->prepare("SELECT Box_Num,Timestamp,E3_SN,Assy_Status FROM Current_Box WHERE Box_Num IN( $products )");
$stmt->execute($zzz);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
unset($zzz);
$e++;
}
and from https://stackoverflow.com/a/2814703/
$ids = array(2, 4, 6, 8);
// prepare a string that contains ":id_0,..,:id_n" and include it in the SQL
$plist = ':id_'.implode(',:id_', array_keys($ids));
$sql = "SELECT * FROM someTable WHERE someId IN ($plist)";
// prepare & execute the actual statement
$parms = array_combine(explode(",", $plist), $ids);
$stmt = $PDO->prepare($sql);
$rows = $stmt->execute($parms);
From comments:
"You might want to use association tables rather than storing the information the way you are storing it. – Maximus2012"
As mentioned in the comments, some questions/answers from SO that demonstrate the concept of Association tables along with composite primary keys:
Mysql : Association table
How to use an MySQL association table to return categories not currently assigned to an entry
If OP decides to go with this structure then the queries would need to be changed to make use of LEFT JOIN and/or use a sub-query with IN clause. There are plenty of examples of both on SO. One that I could find with a simple search (please ignore the slow query part and look at the examples to demonstrate the concept):
MySQL - SELECT WHERE field IN (subquery) - Extremely slow why?

Related

PHP/MYSQL:Carry out UPDATE within SELECT query

There are many questions on SO about this but I cannot find one that quite meets my situation.
I want to use the values in some fields/columns of a table to set the value of a third field/column
In other words something like:
table races
athleteid|difficulty|score|adjustedscore
$sqlSelect = "SELECT athleteid,difficulty,score FROM races";
$res = mysql_query($sqlSelect) or die(mysql_error());
while ($row = mysql_fetch_array($res)){
$adjustedscore=difficulty*score;
$sqlupdate = "UPDATE race, set adjustedscore = '$adjustedscore' WHERE athletes = 'athletes'";
$resupdate = mysql_query($sqlupdate);
}
My understanding, however, is that MYSQL does not support update queries nested in select ones.
Note, I have simplified this slightly. I am actually calculating the score based on a lot of other variables as well--and may join some tables to get other inputs--but this is the basic principal.
Thanks for any suggestions
You can run:
UPDATE `races`
SET `adjustedscore` = `difficulty` * `score`
WHERE `athleteid` IN (1, 2, 3, ...)
First of all, as previous commentators said, you should use PDO instead of mysql_* queries.
Read about PDO here.
When you'll get data from DB with your SELECT query, you'll get array. I recommend you to use fetchAll() from PDO documentation.
So, your goal is to save this data in some variable. Like you did with $row.
After that you'll need to loop over each array and get your data:
foreach($row as $r) {
//We do this to access each of ours athlete data
$adjustedscore= $row[$r]["difficulty"]* $row[$r]["score"];
//Next row is not clear for me...
$query = "UPDATE race SET adjustedscore = '$adjustedscore' WHERE athletes = 'athletes'";
And to update we use PDO update prepared statement
$stmt = $dbh->prepare($query);
$stmt->execute();
}

How to Search Values in all table in a mysql database?

How i find the Last Updated Values inside the all the table field in a given Database?
Search results for "%2015-07-08%" at least one of the words:
Its not impossible, but its not trivial either. I don't think that there is an easy way to do this with SQL alone (I assume that you use mySQL, but you haven't really specified what kind of database you are using).
One way to do it is make a script that uses INFORMATION_SCHEMA tables to find the relevant tables and columns to search through, then iterate those in PHP and execute queries that search those columns and tables.
Edit:
Just for the sake of doing it I made a small example of what i mean, this code uses PDO:
function findAll($search_str, $database, $types = ['tinytext','blob','varchar','text','longblob']){
global $pdo;
foreach($types as &$t){
$t = "'" . $t . "'";
}
$types = implode(',',$types);
$s = $pdo->prepare("
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.columns
WHERE
TABLE_SCHEMA = :database
AND DATA_TYPE IN ($types)
");
$s->bindValue(':database', $database);
$s->execute();
$results = [];
foreach($s->fetchAll(\PDO::FETCH_ASSOC) as $column){
$search = $pdo->prepare("SELECT * FROM $database.${column['TABLE_NAME']} WHERE ${column['COLUMN_NAME']} LIKE :search_str");
$search->bindValue(':search_str', $search_str);
$search->execute();
$result = $search->fetchAll(\PDO::FETCH_ASSOC);
if(count($result))
$results[$column['TABLE_NAME']] = isset($results[$column['TABLE_NAME']])
? array_merge(
$results[$column['TABLE_NAME']],
$result
)
: $result;
}
return $results;
}
Example of usage:
findAll('%foobar%','my_database');
findAll('%2015-07-08%','my_database',['date','datetime','timestamp']); //Only search date types...
How about checking the latest value of the key column e.g. in an column with auto increment you check the highest value? This is just a suggestion though while assuming you have such a column. The other idea would be to add a column with a timestamp data type so that you can update it automatically during inserts or updates.

passing parameter to select statement from url

I have a database with a table which has two columns, lets say aa_id and bb_id - each of the the columns is a foreign key relating to another table and both columns are making a composite key for this particular table. there are several rows containing either the same aa_id and different bb_id or the same bb_id and different aa_id.
using pdo I want to extract the rows of the same - let's say - aa_id and I want to do this passing the parameter value in url. so the result of the select statement should be several rows and they should be saved as - for example - an array.
I have tried to do this with following code:
$sql = sprintf("select aa_id, bb_id from a_table where aa_id=:aa_id");
$res = $db->query($sql);
$rows = $res->fetch(PDO::FETCH_ASSOC);
foreach($rows as $key=>$value)
{
echo $key . " - " . $value . "</br>";
}
And it give no result.
I does work if I state the value of aa_id in the query like this
$sql = sprintf("select aa_id, bb_id from a_table where aa_id=191919");
, but it extracts no data if I put the value in url.
I am not really sure what to search for in the web because I don't know what's the notation called (if it is). If somebody could tell me what may be wrong with the code or give me directions to what I should look for in the web among tutorials or documentation I will be grateful. Perhaps somebody could recommend a good source of knowledge about mysql, php and pdo... Thanks in advance.
Well yeah, :indicator doesn't just automatically load in $_GET['indicator'], you need to manually bind it.
Assuming the URL ends with, ?aa_id=191919, your code might look something like this:
$sql = "select aa_id, bb_id from a_table where aa_id=:aa_id";
$res = $db->prepare($sql);
$res->bindValue(':aa_id', $_GET['aa_id'], PDO::PARAM_INT);
$res->execute();
$rows = $res->fetch(PDO::FETCH_ASSOC);
while($row=$res->fetch(PDO::FETCH_ASSOC))
{
print_r($row);
}

PHP MySQL multiple id insert and set name

I've got this POST form in my website designed to make groups out of an unspecified number users. It works by while looping out all the users in my database with a check box next to their names. You tick the boxes of the users you want, give the group a name then submit the form.
To accomplish the above I need to do two queries due to the way the database has been set up. The table is called Participant/Group and it contains 3 columns: idParticipant, idGroup and GroupName. Here's what I have so far but it has its flaws:
$aParticipants = array_map('mysql_real_escape_string', $_POST['check']);
$pIn = implode("),(", $aParticipants);
$gIn = implode("', '", $aParticipants);
$query1 = mysql_query("INSERT INTO `Participant/Group` (`idParticipant`) VALUES ($pIn);");
$query2 = mysql_query("UPDATE `Participant/Group` SET GroupName = '".$_POST['group']."' WHERE idParticipant IN ('$gIn')");
So the first query inserts the id's of the users into the database and the second query adds the group name to each of those newly inserted id's. If you could combine these two queries I think it could solve all my problems but I'm pretty sure the syntax doesn't allow it.
Anyway the problem with the above code is that it overwrites the database with any subsequent overlapping queries. The important thing to remember here is users are not restricted to one group. A user with an id of 7 can be in a Group called Group A and also be in a group called Group C. There will need to be two separate rows to record this. With my code above it is creating the separate rows but both of them will have the group name of whatever was last submitted in the form.
Anyone know how my code could be tweaked (re-written if you want) to fix this?
Add group name in implode
$aParticipants = array_map('mysql_real_escape_string', $_POST['check']);
$group = mysql_real_escape_string($_POST['group']);
$pIn = implode(", {$group}),(", $aParticipants);
$query1 = mysql_query("INSERT INTO `Participant/Group` (`idParticipant`, `GroupName`) VALUES ($pIn);");
It could be done using only one query. Also, the group field must also be sanitized using mysql_real_escape_string to avoid SQL injection attacks.
$aParticipants = array_map('mysql_real_escape_string', $_POST['check']);
$group = mysql_real_escape_string($_POST['group']);
$sqlvalues = array();
foreach ($aParticipants as $p) {
$sqlvalues[] = "('$p', '$group')";
}
$values = implode(',', $sqlvalues);
mysql_query("INSERT INTO `Participant/Group` (`idParticipant`, GroupName)
VALUES $values");
For the sake of completeness, the best would be to use MySQLi or PDO to take advantage of prepared statements for the sake of performance and security.
$aParticipants = array_map('mysql_real_escape_string', $_POST['check']);
$participants = array();
foreach(aParticipants as $p) {
$participants[] = $p . ', ' . mysql_real_escape_string($_POST['group']);
}
$pIn = implode("),(", $participants);
$query1 = mysql_query("INSERT INTO `Participant/Group` (`idParticipant`, `GroupName`) VALUES ({$pIn})");
EDIT the problem here is that the $iPn string will contain ,( at the end that causes SQL error (which it did not when inserting just one value into one column).
Therefore a line
$pIn = implode("),(", $participants);
has to be replaced by
$pIn = substr(implode("),(", $participants), 0, -3);
Now it should work without any SQL errors...

Subquery in PHP

Let's put an easy example with two tables:
USERS (Id, Name, City)
PLAYERS (Id_Player, Number, Team)
And I have to do a query with a subselect in a loop, where the subselect is always the same, so I would like to divide it into two queries and put the subselect outside the loop.
I explain. What works but it is not optimize:
for($i=0;$i<something;$i++)
{
$res2=mysql_query("SELECT Team from PLAYERS WHERE Number=$i
AND Id_Player IN (SELECT Id FROM USERS WHERE City='London')");
}
What I would like to do but it doesn't work:
$res1=mysql_query("SELECT Id from USERS where City='London'");
for($i=0;$i<something;$i++)
{
$res2=mysql_query("SELECT Team from PLAYERS WHERE Number=$i
AND Id_Player IN **$res1**");
}
Thanks!
Something like this should work.
<?
$sql = "SELECT Team from PLAYERS
JOIN USERS on (Id_player=Id)
WHERE Number BETWEEN $minID AND $maxID
AND City='London'
GROUP BY Team";
$results=mysql_query($sql) or die(mysql_error());
// $results contain all the teams from London
// Use like normal..
echo "<ul>\n";
while($team = mysql_fetch_array($results)){
echo "\t<li>{$team['Team']}</li>\n";
}
echo "</ul>";
Placing SQL quires in loops can be very slow and take up a lot of resources, have a look at using JOIN in you SQL. It's not that difficult and once you've got the hang of it you can write some really fast powerful SQL.
Here is a good tutorial worth having a look at about the different types of JOINs:
http://www.keithjbrown.co.uk/vworks/mysql/mysql_p5.php
SELECT PLAYERS.*, USERS.City FROM PLAYERS, USERS WHERE USERS.City='London' AND PLAYERS.Number = $i
Not the best way to do it; maybe a LEFT JOIN, but it should work. Might have the syntax wrong though.
James
EDIT
WARNING: This is not the most ideal solution. Please give me a more specific query and I can sort out a join query for you.
Taking your comment into account, let's take a look at another example. This will use PHP to make a list we can use with the MySQL IN keyword.
First, make your query:
$res1 = mysql_query("SELECT Id from USERS where City='London'");
Then, loop through your query and put each Id field one after another in a comma seperated list:
$player_ids = "";
while($row = mysql_fetch_array($res1))
{
$player_ids .= $row['Id'] . ",";
}
$player_ids = rtrim($player_ids, ",");
You should now have a list of IDs like this:
12, 14, 6, 4, 3, 15, ...
Now to put it into your second query:
for($i = 0; $i<something; $i++)
{
$res2 = mysql_query("SELECT Team from PLAYERS WHERE Number=$i
AND Id_Player IN $player_ids");
}
The example given here can be improved for it's specific purpose, however I'm trying to keep it as open as possible.
If you want to make a list of strings, not IDs or other numbers, modify the first while loop, replacing the line inside it with
$player_ids .= "'" . $row['Id'] . "',";
If you could give me your actual query you use, I can come up with something better; as I said above, this is a more generic way of doing things, not necessarily the best.
Running query in a loop is not a great idea. Much better would be to get whole table, and then iterate through table in loop.
So query would be something like that:
"SELECT Team from PLAYERS WHERE Number BETWEEN($id, $something)
AND Id_Player IN (SELECT Id FROM USERS WHERE City='London')"
$res1=mysql_query("SELECT Id from USERS where City='London'");
for($i=0;$i<something;$i++)
{
$res2=mysql_query("SELECT Team from PLAYERS WHERE Number=$i
AND Id_Player IN **$res1**");
}
Would work, but mysql_query() returns a RESULT HANDLE. It does not return the id value. Any select query, no matter how many, or few, rows it returns, returns a result statement, not a value. You first have to fetch the row using one of the mysql_fetch...() calls, which returns that row, from which you can then extract the id value. so...
$stmt = mysql_query("select ID ...");
if ($stmt === FALSE) {
die(msyql_error());
}
if ($stmt->num_rows > 0) {
$ids = array();
while($row = mysql_fetch_assoc($stmt)) {
$ids[] = $row['id']
}
$ids = implode(',', $ids)
$stmt = mysql_query("select TEAM from ... where Id_player IN ($ids)");
.... more fetching/processing here ...
}

Categories