PDO UNION with ? not working - php

I am new to SQL and PDO and PHP so I know I am asking a lot of myself. Still nothing ventured...
I want to combine the results of two queries and am using aliases to make the column names the same for the UNION query.
I have tried all sorts of reducing till there is nothing left to reduce, there are many more in the actual result I need for my app. I have the following code by can't think why it is not working.
Both queries work on their own but I get nothing when I combine them with a UNION. Any suggestions would be most helpful.
include ("conn/dbCon_1.php");
$sql= "(SELECT First_Name AS myResult FROM tbl_User WHERE First_Name LIKE ?)";
$sql.=" UNION ALL ";
$sql.= "(SELECT Course_Title AS myResult FROM tbl_Course WHERE Course_Title LIKE ? )";
$c1 = "%le%";
try {
$qResults = $dbConn->prepare($sql);
$qResults->execute([$c1]);
$qResults->fetch(PDO::FETCH_ASSOC);
return $qResults;
//Close connection
$dbConn = null;
} catch(PDOExcepetion $e) {
echo $e->getMessage();
}
Many thanks in anticipation and thank you for your kind attention.
Bri

As you have two placeholders - you should bind values twice:
$qResults->execute([$c1, $c1]);

You invoke the query with two parameters (like in the first Query and like in the second) even if they have the same value .. so you have to pass two parameters
$qResults->execute([$c1, $c1]);

Related

Using a PHP Variable in a MySQL Query

So I have the following MySQL query that I want to execute through a PHP script:
for($y=0;$y<$usercount;$y++){
$findweight = "replace into weight (user_id, column1)
select user_id,
0.4*column1_a+0.6*column1_bon as calc1
from history_summary where user_id=$y";
if (mysqli_query($link, $findweight)) {
echo "success <br>";
} else {
echo "Error: " . $sql . "<br>" . mysqli_error($link);
}
}
But somehow everytime I execute the script it fails to work. Everytime the script is executed, the text "success" is outputted, which means that the MySQL query should have been successfully executed, but when I check my database, nothing seems to have changed. Yet when I run the query directly such as the following:
replace into weight (user_id, column1)
select user_id,
0.4*column1_a+0.6*column1_bon as calc1
from history_summary where user_id=1
It works just fine. I'm assuming the issue is that the variable $y failed to be passed on properly to the query, but I'm not quite sure. I've tried the other solutions posted on this site but none of them seem to work. If anyone can help out that'd be great!
The DB part of me is crying because you should really be submitting one query instead of multiple queries. Specifically, if $y is a safe variable, you should have something like this:
$sql = "replace into weight (user_id, column1)
select user_id,
0.4*column1_a+0.6*column1_bon as calc1
from history_summary where user_id < $y";
There are other questions I have, such as if you really want REPLACE or you want UPDATE but that is a problem for another day.
BUT, your question was more about debugging, and it seems that the command(s) are executing successfully. Try running your query on many different values of $y. Perhaps you have encountered an edge case
The question is about debugging, so I'll respond to that, but I double-down on #mankowitz points below.
Debugging
Do you have access to the DB server? Can you watch the query log on the server to confirm that it received what you think the code is sending?
Try the old standby of println style debugging and echo out the SQL string before sending. The <pre> and --- help to make sure you are able to see any extraneous characters you might have in your SQL string:
...
echo "About to send SQL: <pre>--- $findweight ---</pre>\n"
if (mysqli_query($link, $findweight)) {
...
Is this code wrapped inside of a SQL transaction that is not (auto)committed when the script ends?
Do other, perhaps simpler queries work? Have you tried the simple SELECT 1 and echoed out the result?
More arcane and improbable given the context of the question: is fsync disabled on the server? If so, then each mysql_query does not guarantee the DB has actually written the contents to disk yet, and you may eventually see the rows get updated.
What does mysqli_query return? The code currently ignores the result other than checking if it's falsey. Store the result and introspect it.
An edge case of mysqli_query. Ten plus years ago, I encountered cases where mysql_query (note the lack of i) would not return FALSE despite a failing query. It was an oddball case of the connected user not having access to manipulate or view the rows in question, highlighting a bug in mysql_query as well as my connection string.
Database interaction
Be smart about DB queries, minimize the communication, and use bulk operations wherever possible. Your code, as structured could be rewritten in a couple of ways, both of which require only a single call to the database:
The WHERE-IN construct allows you to be very precise about which rows you address:
$ids = [];
for ( $y = 0; $y < $usercount; ++$y )
$ids[] = $y;
$ids = implode(',', $ids);
$findweight = "REPLACE INTO weight (user_id, column1)
SELECT user_id, 0.4*column1_a + 0.6*column1_bon
FROM history_summary WHERE user_id IN ($ids)";
Or, since the IDs the code addresses are contained within a contiguous range, do as #mankowitz suggested, removing the need for a for-loop entirely:
$findweight = "REPLACE INTO weight (user_id, column1)
SELECT user_id, 0.4*column1_a + 0.6*column1_bon
FROM history_summary WHERE user_id BETWEEN 0 AND $usercount";
# alternate form
$findweight = "REPLACE INTO weight (user_id, column1)
SELECT user_id, 0.4*column1_a + 0.6*column1_bon
FROM history_summary WHERE 0 <= user_id AND user_id <= $usercount";
If you absolutely must use individual per-row statements, consider a prepared statement so the DB need only parse and plan the statement once:
$findweight = 'REPLACE INTO weight (user_id, column1)
SELECT user_id, 0.4*column1_a + 0.6*column1_bon
FROM history_summary WHERE user_id = ?';
if ($psth = mysqli_prepare($link, $findweight)) {
$y = 0;
mysqli_stmt_bind_param($psth, 'i', $y);
while ( ++$y < $usercount ) {
if ( mysqli_stmt_execute( $psth ) ) {
echo "Successful REPLACE operation for user_id = $y<br>\n";
}
else {
echo "Error in REPLACE operation for user_id = $y<br>\n";
break;
}
}
}

Right join cannot access Row from other table in PHP

$query = "SELECT `Title`, `Date`, `Url`, `Url_Hash`
FROM filings
RIGHT JOIN form_attributes ON
filings.Url_Hash=form_attributes.Unique_Hash
ORDER BY filings.Date ASC
$result = mysqli_query( $mysqli, $query);
while ($row = mysqli_fetch_assoc($result)):
$title = row['col_name_in_form_attributes']; // undefined index error
This is pretty basic but has me stuck. I have 2 tables, filings and form_attributes. I want to access the row names of form_attributes, but get an Undefined index error.
As a workaround, I suppose I could do this with STMT like so:
$stmt = $mysqli->prepare($query);
$stmt->execute();
$stmt->bind_result($result1, $result2, /* etc */);
$stmt->store_result();
However, bind_result() is inefficient as I have over a dozen columns. Much easier to use $row['xyz']; STMT also does not work with MySQL full text search which I am using. Is there a way to do this with mysqli_query or is my SQL incorrect? Thanks.
Not an answer, but FWIW, I find this easier to conceptualise...
SELECT Title
, Date
, Url
, Url_Hash
FROM form_attributes a
LEFT
JOIN filings f
ON f.Url_Hash = a.Unique_Hash
ORDER
BY f.Date ASC
I was forgetting to explicitly call the name of the table plus the column name in my query. Example:
`form_attributes`.`Contact_Info`
Works now!

Is it possible to use the AND clause in a MYSQL JOIN statement?

Im currently using PDO to make my database queries, i find that that the query doesnt run when i append the "AND IFC.location= :location" section of the query, is the problem arising from using an AND clause while im already using the query to JOIN two tables? (the 'tables' table and the 'IFC' table)
$location= '1';
echo "<pre>";
$sql="SELECT name from IFC,tables
WHERE IFC.tablename=tables.id AND IFC.location=:location
ORDER BY Numopinions DESC
";
$stmt= $dbh->prepare($sql);
$stmt->bindParam(":location", $location);
if($stmt->execute())
{
$rows = $stmt-> fetchAll();
print_r($rows);
}
Yes. Your query should work, but the proper syntax would use explicit JOIN:
SELECT name
FROM IFC JOIN
tables
ON IFC.tablename = tables.id AND IFC.location = :location
ORDER BY Numopinions DESC;
Is there a reason you think your query does not work?
Yes AND can be used in joins also. If you think your statement is not working, just try to use without prepare statement and see the result.

PHP Prepared Statement variable binding error with subquery

I have a query with a few subqueries like so
SELECT ...
FROM (SELECT ...
FROM ...
GROUP BY ...) as speedLimitCalc INNER JOIN
(SELECT ...
FROM date a INNER JOIN HOURLY_TEST b ON a.[FULL_DAY_DT] = b.DATE
WHERE (b.DATE BETWEEN '".$date_s."' AND '".$date_e."')
AND HOUR BETWEEN ".$time_s." AND ".$time_e."
AND(LKNO BETWEEN '".$lkno_s."' and '".$lkno_e."')
AND RDNO= '".$rdno."'
AND pub_hol IN (".$pubholquery.")
AND school_hol IN (".$schholquery.")
AND day_no IN (".$dayquery.")
GROUP BY RDNO, LKNO, PRESCRIBED_DIRECTION, CWAY_CODE) as origtable ON ...
,(SELECT ...
FROM [Dim_date]
WHERE (FULL_DAY_DT BETWEEN '".$date_s."' AND '".$date_e."')
AND pub_hol IN (".$pubholquery.")
AND school_hol IN (".$schholquery.")
AND day_no IN (".$dayquery.") ) as c
ORDER BY ...
where I am inserting variables in the inner query where clause.
I am trying to parametrize this query using odbc_prepare and odbc_execute, however I am running into issues of binding the variables. At present, when I use the following
$result = odbc_prepare($connection, $query);
odbc_execute($result)or die(odbc_error($connection));
to run this query, everything works fine. However, when I try to bind a variable, such as
AND RDNO= ?
...
odbc_execute($result, array($rdno))or die(odbc_error($connection));
I get the following error message.
PHP Warning: odbc_execute() [/phpmanual/function.odbc-execute.html]: SQL error: [Microsoft][ODBC SQL Server Driver]Invalid parameter number, SQL state S1093 in SQLDescribeParameter
My guess is that it's because I'm binding a variable in a subquery, since this procedure works when the Where clause is in the top Select query.
I was wondering whether anyone else has encountered this issue before, and how they solved it? Thanks
Fixed the issue by removing the need for parameters in the subquery by separating the query into multiple queries using temporary tables.
$query = "SELECT ...
INTO ##avgspeedperlink
FROM Date a INNER JOIN HOURLY_TEST ON a.[FULL_DAY_DT] = b.DATE
WHERE (b.DATE BETWEEN ? AND ?)
AND HOUR BETWEEN ? AND ?
AND(LKNO BETWEEN ? and ?)
AND RDNO= ?
AND pub_hol IN (".$pubholquery.")
AND school_hol IN (".$schholquery.")
AND day_no IN (?,?,?,?,?,?,?)
GROUP BY RDNO, LKNO, PRESCRIBED_DIRECTION, CWAY_CODE";
$result = odbc_prepare($connection, $query);
odbc_execute($result, array($date_s,$date_e,$time_s,$time_e,$lkno_s,$lkno_e,$rdno,$daysanitised[0],$daysanitised[1],$daysanitised[2],$daysanitised[3],$daysanitised[4],$daysanitised[5],$daysanitised[6]))or die(odbc_error($connection));
$query = "SELECT ...
INTO ##daysinperiod
FROM [RISSxplr].[dbo].[Dim_date]
WHERE (FULL_DAY_DT BETWEEN ? AND ?)
AND pub_hol IN (".$pubholquery.")
AND school_hol IN (".$schholquery.")
AND day_no IN (?,?,?,?,?,?,?)";
$result = odbc_prepare($connection, $query);
odbc_execute($result, array($date_s,$date_e,$daysanitised[0],$daysanitised[1],$daysanitised[2],$daysanitised[3],$daysanitised[4],$daysanitised[5],$daysanitised[6]))or die(odbc_error($connection));
$query = "SELECT ...
FROM ##avgspeedperlink, ##daysinperiod
ORDER BY LKNO, OUTBOUND
drop table ##avgspeedperlink
drop table ##daysinperiod";
Note that I had to use double ## for making the temporary tables (single # means that table is local to the query, ## means that the temporary table becomes global for multiple queries).

Running multiple MySQL queries with user defined variable through PHP

I'm trying to run a combination of queries from PHP. Something like this:
SELECT #rownum:=0; INSERT INTO tbl1 (`myId`, `rank`) (SELECT myId, #rownum:=#rownum+1 FROM `tbl2` WHERE 1 ORDER BY rank DESC)
Because of the user-defined var (#rownum) I have to run these queries "together". I've tried doing it either with mysqli or PDO, but both seemed to block this.
The mysqli usage I tried was:
public function multiQuery($query) {
if (#parent::multi_query($query)) {
$i = 0;
do {
$i++;
} while (#parent::next_result());
}
if (!$result) {
printf("MySQLi error:<br><b>%s</b><br>%s <br>", $this->error, $query);
}
return $result;
}
And in PDO I just expected it to work with the query() func.
How can I overcome this?
This might work better:
(set tbl1.rank to autoincrement)
TRUNCATE tbl1;
INSERT INTO tbl1 (myId) SELECT myId FROM tbl2 ORDER BY rank DESC;
It's two separate commands but you won't have to worry about the variable issue. It doesn't answer the question "how to run two different commands in one string" or "how to use variables in a query with PHP" but if you're just trying to re-rank things, that should work.
Truncate will empty tbl1 and reset the autoincrement value back to 1

Categories