This is probably very simple (I'm a novice), but I haven't been able to find an answer.
I'm using Linux, DB2 and PHP.
My simple DB2 query from PHP only returns rows with integer values, but fails with "Fetch Failure" for anything else (varchar ...).
The query works with db2cli for all values:
echo "select COLUMN from TEST.TABLE"" | ./db2cli execsql -dsn SCHEMA
But fails in PHP:
$conn_string = "DRIVER={IBM DB2 ODBC DRIVER};DATABASE=$database;" .
"HOSTNAME=$hostname;PORT=$port;PROTOCOL=TCPIP;UID=$user;PWD=$passwd;";
$conn = db2_pconnect($conn_string, '', '');
if ($conn) {
$sql = 'select COLUMN from TEST.TABLE';
$options = array('cursor' => DB2_SCROLLABLE, 'binmode' => DB2_BINARY);
$stmt = db2_prepare($conn, $sql, $options);
if ($stmt) {
$result = db2_execute($stmt);
if (!$result) {
echo "exec errormsg: " .db2_stmt_errormsg($stmt);
}
$total_rows = db2_num_rows($stmt);
print "<br>Total rows: $total_rows";
for ($i = 0; $i < $total_rows; $i++) {
$row = db2_fetch_array($stmt);
print "<br>$row[0]";
}
} else {
echo "exec erromsg: " . db2_stmt_erromsg($stmt);
}
db2_close($conn);
} else {
echo "failed #2 ".db2_conn_errormsg();
}
}
It will display any rows with integer values, but empty strings for everything else with the error "Fetch Failure" in the log. I tried db2_fetch_array, db2_fetch_assoc and db2_fetch_both.
Note: I've added the superfluous stuff like db2_scrollable and db2_num_rows later on in attempts to solve the problem. Unsuccessfully.
EDIT: I can even FILTER by the values that won't display ( SELECT column WHERE column = 'value') and it'll return the correct number of rows.
Related
I have an unusually long query (13sec+ for our system) that returns no results while using sqlsrv_query, but gives me 331 rows when I enter directly the SQL query on the server. sqlsrv_num_rows returns 0 and sqlsrv_errors is empty.
<?php
$connInfo = array( "Database"=>"xxx", "UID"=>"xxx", "PWD"=>"xxx", "CharacterSet" => "UTF-8");
$conn = sqlsrv_connect('SQL2008', $connInfo);
if ($conn)
{
$sql_q = "SELECT TblOrder.FldJobNb, TblOrder.FldOrdCre As DateReception, TblOrder.FldReclamerDate As DateDebutPORev, TblOrder.FldPOReviewApprovedDate As DateFinPORev,
TblOrder.FldPrinted, capsule_order.temps_reception_planification As DateReceptionPLANIF, TblOrder.FldPriced,
CASE
WHEN ISNULL(TblOrder.FldContractReviewCompletedDate, 0) = 0
THEN capsule_order.temps_reception_planification
ELSE TblOrder.FldContractReviewCompletedDate
END As TempsFinRevue,
(SELECT TOP 1 TblOrderXFeredNotifications.FldDate FROM [TCS].[dbo].[TblOrderXFeredNotifications] WHERE TblOrderXFeredNotifications.FldOrdID = TblOrder.FldOrdID ORDER BY TblOrderXFeredNotifications.FldNoLigne) As DatePlanification,
TblOrder.FldXfer2Sched, TblOrder.FldOrdMod As DateDernierMod, TblOrder.FldOrdStatusDate As DateDernierStatut, TblOrder.FldOrdReq As DateBesoin
FROM [TCS].[dbo].[TblOrder] RIGHT JOIN [TCS].[dbo].[capsule_order] ON TblOrder.FldJobNB = capsule_order.FldJobNB
WHERE '" . $dateDebut->format('Y-m-d H:i:s.').'000' . "' <= TblOrder.FldOrdCre AND TblOrder.FldOrdCre <= '" . $dateFin->format('Y-m-d H:i:s.').'000' . "'";
// die($sql_q); Query that I enter into SQL Server and gives me 331 results after 13secs
$query= sqlsrv_query($conn, $sql_q, array(), array( "Scrollable" => 'static' ));
if ($query)
{
if (sqlsrv_num_rows($query) > 0)
{
while ($result= sqlsrv_fetch_array($query))
{
// ...
}
}
else
{ die(var_dump(sqlsrv_num_rows($query))); }
}
else
{ die("query".$sql_q.'<br>'.print_r( sqlsrv_errors(), true)); }
}
else
{ die ("Connection défectueuse."); } ?>
Thank you a lot for your support,
Renaud
You may consider the following:
Pass datetime values to SQL Server using unambiguous datetime format (yyyy-mm-ddThh:mm:ss.zzz) (my experience is summarized here).
Don't concatenate strings to generate a statement. Always use prepared statements and parameterized queries to prevent SQL injection. With PHP Driver for SQL Server, function sqlsrv_query() does both statement preparation and statement execution and can be used to execute parameterized queries.
If you want to check if the result set from your current statement has one or more rows, you may use sqlsrv_has_rows() instead of sqlsrv_num_rows() and use a default (forward) cursor.
The following example, based on your code, is a possible solution to your problem:
<?php
$connInfo = array( "Database"=>"xxx", "UID"=>"xxx", "PWD"=>"xxx", "CharacterSet" => "UTF-8");
$conn = sqlsrv_connect('SQL2008', $connInfo);
if ($conn)
{
$sql_q = "
SELECT
TblOrder.FldJobNb,
TblOrder.FldOrdCre As DateReception,
TblOrder.FldReclamerDate As DateDebutPORev,
TblOrder.FldPOReviewApprovedDate As DateFinPORev,
TblOrder.FldPrinted, capsule_order.temps_reception_planification As DateReceptionPLANIF, TblOrder.FldPriced,
CASE
WHEN ISNULL(TblOrder.FldContractReviewCompletedDate, 0) = 0 THEN capsule_order.temps_reception_planification
ELSE TblOrder.FldContractReviewCompletedDate
END As TempsFinRevue,
(
SELECT TOP 1 TblOrderXFeredNotifications.FldDate
FROM [TCS].[dbo].[TblOrderXFeredNotifications]
WHERE TblOrderXFeredNotifications.FldOrdID = TblOrder.FldOrdID
ORDER BY TblOrderXFeredNotifications.FldNoLigne
) As DatePlanification,
TblOrder.FldXfer2Sched,
TblOrder.FldOrdMod As DateDernierMod,
TblOrder.FldOrdStatusDate As DateDernierStatut,
TblOrder.FldOrdReq As DateBesoin
FROM [TCS].[dbo].[TblOrder]
RIGHT JOIN [TCS].[dbo].[capsule_order] ON TblOrder.FldJobNB = capsule_order.FldJobNB
WHERE ? <= TblOrder.FldOrdCre AND TblOrder.FldOrdCre <= ?
";
$query = sqlsrv_query(
$conn,
$sql_q,
array($dateDebut->format('Y-m-d\TH:i:s').'.000', $dateFin->format('Y-m-d\TH:i:s').'.000')
);
if ($query)
{
if (sqlsrv_has_rows($query))
{
while ($result= sqlsrv_fetch_array($query))
{
// ...
}
}
else
{ die(var_dump(sqlsrv_num_rows($query))); }
}
else
{ die("query".$sql_q.'<br>'.print_r( sqlsrv_errors(), true)); }
}
else
{ die ("Connection défectueuse."); }
?>
I am working on a website where I can accept user data through multiple different forms to update tables in a database and instead of writing separate functions for each I thought it would be a good idea to use string concatenation and for loops to write the SQL statements for me. Basically it takes in 4 parameters a table, id, the columns that need to be updated (params) and an array of user input. I believe that I am pretty close to what I need but it fails to execute and gives me an error of
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 '(name,comment) VALUES ( 'sadf','asdf') WHERE music_work_ID=14' at line 1
This is what is displayed when I print out $sql,
sql = UPDATE music_work SET (name,comment) VALUES ( :name,:comment) WHERE music_work_ID=14
I don't know if theres a better way of creating something like this or if i'm not using the correct syntax but for now I am at a deadlock.
function music_work_update($userInput, $userID_selection){
foreach ($userInput as $k => $v) {
if($userInput[$k] === '') {
unset($userInput[$k]);
}
}
update("music_work", $userID_selection, ["name", "comment"], $userInput);
}
function update($table, $userID_selection, $params, $input){
$conn = connect();
try {
$sql = "UPDATE ".$table." SET (";
for ($i = 0; $i < sizeof($params); $i++) {
$sql .= "`".$params[$i]."`,";
}
$sql = substr_replace($sql ,"", -1);
$sql .= ") VALUES ( ";
for ($i = 0; $i < sizeof($params); $i++) {
$sql .= ":".$params[$i].",";
}
$sql = substr_replace($sql ,"", -1);
$sql .= ") WHERE `music_work_ID`=$userID_selection";
echo ("sql = $sql <br>");
$command = $conn->prepare($sql);
for ($i = 0; $i < sizeof($params); $i++) {
$command->bindParam(':'.$params[$i], $input[$params[$i]], PDO::PARAM_STR);
}
if ($command->execute()) {
echo "<script type= 'text/javascript'>alert('New Record Inserted Successfully');</script>";
}
else{
echo "<script type= 'text/javascript'>alert('Data not successfully Inserted.');</script>";
}
echo "failed before execute";
$conn = null;
}
catch(PDOException $e)
{
echo ($e->getMessage());
}
}
You confuse multiple INSERT INTO and multiple UPDATE.
For multiple UPDATE use:
UPDATE music_work SET name = x, comment = y WHERE id = z;
For multiple INSERT INTO:
INSERT INTO table_name (column_list)
VALUES
(value_list_1),
(value_list_2);
I have an old PHP code that has mysql in it.
It gets an array from a SELECT statement, adds it to a JSON object, as a property and echoes the encoded JSON.
I changed it around to use mysqli, but when I try to get the rows, and create an array out of them, it just returns nothing.
Here's the old mysql code:
$con = mysql_connect('host','account','password');
if (!$con)
{
//log my error
};
mysql_select_db("database_name", $con);
mysql_set_charset('utf8');
$sql = "SELECT field1 as Field1, field2 as Field2 from table where ID = '".$parameter."'";
$query = mysql_query($sql);
$results = array();
while($row = mysql_fetch_assoc( $query ) )
{
$results[] = $row;
}
return $results;
Version1: Here's the new one that I tried writing:
$con = mysqli_connect('host','account','password','database_name');
$sql = "SELECT field1 as Field1, field2 as Field2 from table where ID = '".$parameter."'";
$results = array();
if($result=mysqli_query($con, $sql))
{
while ($row=mysqli_fetch_assoc($result))
{
$results[] = $row;
}
return $results;
}
else
{
//error
}
Version2: Second thing I tried, which only returns 1 ROW:
...same as above until $sql
if($result=mysqli_query($con,$sql))
{
$row=mysqli_fetch_assoc($result);
return $row;
}
Version3: Or I tried to completely mirror the mysql structure like this:
$sql = "SELECT ...";
$query = mysqli_query($con, $sql);
$results = array();
while($row = mysqli_fetch_assoc( $query ) )
{
$results[] = $row;
}
return $results;
Wrapping the resulting array into the JSON:
$obj = new stdClass();
$obj->Data = $results;
$obj->ErrorMessage = '';
die(json_encode($obj)); //or echo json_encode($obj);
None of the mysqli version are working, so I was thinking there might be an important change in the way these arrays are created.
Any tips on what could be wrong on the first mysqli example?
With Version2 I can tell that the SQL connection is there, and I can at least select a row. But it's obviously only one row, than it returns it. It makes me think, that building up the array is the source of the problem, or it's regarding the JSON object...
LATER EDIT:
OK! Found a working solution.
ALSO, I played around with the data, selected a smaller chunk, and it suddenly worked. Lesson from this: the function is not responding the same way for 40 rows or for 5 rows. Does it have something to do with a php.ini setting? Or could there be illegal characters in the selection? Could it be that the length of a 'Note' column (from the db) is too long for the array to handle?
Here's the working chunk of code, that selects some rows from the database, puts them into an array, and then puts that array into an object that is encoded into JSON at the end, with a statusmessage next to it. Could be improved, but this is just for demo.
$con = mysqli_connect('host','username','password','database_name');
if (!$con)
{
$errorMessage = 'SQL connection error: '.$con->connect_error;
//log or do whatever.
};
$sql = "SELECT Field1 as FieldA, field2 as FieldB, ... from Table where ID='something'";
$results = array();
if($result = mysqli_query($con, $sql))
{
while($row = mysqli_fetch_assoc($result))
{
$results[] = $row;
}
}
else
{
//log if it failed for some reason
die();
}
$obj->Data = $results;
$obj->Error = '';
die(json_encode($obj));
Question is: how can I overcome the issue regarding the size of the array / illegal characters (if that's the case)?
Your "Version 1" seems to be correct from a PHP perspective, but you need to actually handle the errors - both when connecting and when performing the query. Doing so would have told you that you don't actually query a table, you're missing FROM tablename in the query.
Use mysqli_connect_error() when connecting, and mysqli_error($con) when querying to get back the actual errors. General PHP error-reporting might also help you.
The code below assumes that $parameter is defined prior to this code.
$con = mysqli_connect('host','account','password','database_name');
if (mysqli_connect_errno())
die("An error occurred while connecting: ".mysqli_connect_error());
$sql = "SELECT field1 as Field1, field2 as Field2
FROM table
WHERE ID = '".$parameter."'";
$results = array();
if ($result = mysqli_query($con, $sql)) {
while ($row = mysqli_fetch_assoc($result)) {
$results[] = $row;
}
return $results;
} else {
return mysqli_error($con);
}
Error-reporing
Adding
error_reporting(E_ALL);
ini_set("display_errors", 1);
at the top of your file, directly after <?php would enable you to get the PHP errors.
NOTE: Errors should never be displayed in a live environment, as it might be exploited by others. While developing, it's handy and eases troubleshooting - but it should never be displayed otherwise.
Security
You should also note that this code is vulnerable to SQL-injection, and that you should use parameterized queries with placeholders to protect yourself against that. Your code would look like this with using prepared statements:
$con = mysqli_connect('host','account','password','database_name');
if (mysqli_connect_errno())
die("An error occurred while connecting: ".mysqli_connect_error())
$results = array();
if ($stmt = mysqli_prepare("SELECT field1 as Field1, field2 as Field2
FROM table
WHERE ID = ?")) {
if (mysqli_stmt_bind_param($stmt, "s", $parameter)) {
/* "s" indicates that the first placeholder and $parameter is a string */
/* If it's an integer, use "i" instead */
if (mysqli_stmt_execute($stmt)) {
if (mysqli_stmt_bind_result($stmt, $field1, $field2) {
while (mysqli_stmt_fetch($stmt)) {
/* Use $field1 and $field2 here */
}
/* Done getting the data, you can now return */
return true;
} else {
error_log("bind_result failed: ".mysqli_stmt_error($stmt));
return false;
}
} else {
error_log("execute failed: ".mysqli_stmt_error($stmt));
return false;
}
} else {
error_log("bind_param failed: ".mysqli_stmt_error($stmt));
return false;
}
} else {
error_log("prepare failed: ".mysqli_stmt_error($stmt));
return false;
}
References
http://php.net/mysqli.prepare
How can I prevent SQL injection in PHP?
How to check MySQL results are empty or not. If MySQL query results are empty then else condition should not be executed.
In case MySQL results in data there & in else condition my error my message is there but it is not showing any error message.
I have tried the following code but not showing any alert or echo message on the screen.
<?php
$sql = "select * from hall_search_data_1 where rent BETWEEN '".$_SESSION['amount1']."' AND '".$_SESSION['amount2']."'";
$res = mysql_query($sql);
if (!empty($res)) {
while ($row = mysql_fetch_row($res)) {
// here my data
}
} else {
echo "no results found";
}
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
$conn = new mysqli($servername, $username, $password, $dbname);
$sql = "SELECT id, firstname, lastname FROM MyGuests";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "id: " . $row["id"] . " - Name: " . $row["firstname"] . " " . $row["lastname"] . "<br>";
}
} else {
echo "0 results";
}
$conn->close();
?>
Check number of rows
$result = mysqli_query($conn, $sql);
$rowcount=mysqli_num_rows($result);
if($rowcount > 0){
echo "Number of rows = " . $rowcount;
}
else
{
echo "no record found";
}
You can use mysql_num_rows to get count of number of rows returned from query.
if(mysqli_num_rows($res) > 0)
{
// rest of your stuff
}
else
{
echo "No records found.";
}
Note: mysql is deprecated instead use mysqli or PDO as seen above
Security Tip First of all stop using the mysql_* functions because they are not secure for production and later versions has stopped support for this API. So if accidentally you used those function in production then you can be in trouble.
It is not recommended to use the old mysql extension for new development, as it was deprecated in PHP 5.5.0 and was removed in PHP 7. A detailed feature comparison matrix is provided below. More Read
For your answer you have to only check no of rows is zero or not
Read this Post at php documentation with Example.
mysqli_num_rows
mysql_* API has been removed from PHP long time ago. To access the database you should use PDO. Checking if PDO has returned any results is actually pretty simple. Just fetch the results and if the array is empty then there was nothing returned from MySQL.
$stmt = $pdo->prepare('SELECT * FROM hall_search_data_1 WHERE rent BETWEEN ? AND ?');
$stmt->execute([$_SESSION['amount1'], $_SESSION['amount2']]);
$records = $stmt->fetchAll();
if ($records) {
foreach ($records as $row) {
// your logic
}
} else {
echo 'No records found!';
}
There is also mysqli library and if you are stuck using it you have to do a little more work, but the idea is the same. Fetch all results and if nothing was fetched then it means MySQL returned no rows.
$stmt = $mysqli->prepare('SELECT * FROM hall_search_data_1 WHERE rent BETWEEN ? AND ?');
$stmt->bind_param('ss', $_SESSION['amount1'], $_SESSION['amount2']);
$stmt->execute();
$records = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
if ($records) {
foreach ($records as $row) {
// your logic
}
} else {
echo 'No records found!';
}
You can use mysql_num_rows(); to check your query return rows or not
$sql = "select * from hall_search_data_1 where rent BETWEEN '".$_SESSION['amount1']."' AND '".$_SESSION['amount2']."'";
$res = mysql_query($sql);
$rows=mysql_num_rows($res);
if($rows>0)
{
echo "data return from query";
}else{
echo "data not return";
}
Note:- mysql is deprecated instead use mysqli or PDO
I'm very new to PHP and still learning the basics and I'm stuck on an issue I'm hoping someone could help me with.
I have the following code;
$MfgQuery = "SELECT `Mfg` FROM `categories` WHERE `ID` = 10";
if($MfgQueryRun = mysql_query($MfgQuery)) {
if (mysql_num_rows($MfgQueryRun)==NULL){
echo 'No Mfg Results Returned';
} else {
$Mfg = $MfgQueryRun['Mfg'];
echo $Mfg;
}
} else {
echo 'Query Unsuccessful';
}
But for a reason unknown to me I keep getting 'No Mfg Results Returned' but if I copy and paste the query by itself into the MySQL box in PHPMyAdmin it returns a result properly.
What gives??
BTW, Here's exactly what I can insert into PHP MyAdmin's SQL box;
SELECT `Mfg` FROM `categories` WHERE `ID` = 10
and this returns a result but using the code above, it does not.
If anyone wouldn't mind showing me where I went wrong I'd be most appreciative and I thank you in advance
try this
$MfgQuery = "SELECT `Mfg` FROM `categories` WHERE `ID` = 10";
$MfgQueryRun = mysql_query($MfgQuery) ;
$row = mysql_fetch_array($MfgQueryRun) ;
if (mysql_num_rows($MfgQueryRun)== 0 ){
echo 'No Mfg Results Returned';
} else {
$Mfg = $row['Mfg'];
echo $Mfg;
}
Try
$MfgQuery = "SELECT `Mfg` FROM `categories` WHERE `ID` = 10";
$MfgQueryRun = mysql_query($MfgQuery);
if($MfgQueryRun) {
if (mysql_num_rows($MfgQueryRun) == 0){
echo 'No Mfg Results Returned';
} else {
$Mfg = $MfgQueryRun['Mfg'];
echo $Mfg;
}
} else {
echo 'Query Unsuccessful';
}
if (mysql_num_rows($MfgQueryRun)){
echo 'No Mfg Results Returned';
} else {
$Mfg = $MfgQueryRun['Mfg'];
echo $Mfg;
}
Try this remove the NULL in comparison. because mysql_num_rows returns numeric values.
First, you should not use mysql_* functions, they are deprecated (outdated) as of PHP 5.5.0, and will be removed in the future. Use mysqli instead.
Second, you're not testing properly. PHP has no strong types, so a test '== null' does not always do, what you'll expect. See the PHP manual for comparision operators. To test against null, always use is_null().
Third, you're not fetching the data.
Using MySQLi, the code would look similar to this:
$mysqli = new mysqli("example.com", "user", "password", "database");
if ($mysqli->connect_errno != 0) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
die(); // or return, if in method or function context
}
$result = $mysqli->query("SELECT `Mfg` FROM `categories` WHERE `ID` = 10");
if ($result === false) {
echo "Query failed: (" . $mysqli->errno . ") " . $mysqli->error;
die(); // or return, if in method or function context
}
printf("Select returned %d rows.\n", $result->num_rows);
$row = $result->fetch_assoc();
echo $row['Msg'];
/* free result set */
$result->close();