Read Next Record - php

I am filtering null values, in php on MYSQL. When a null value is read, I need the MySQL to read the next record.
How do I go about doing that?

Why not filtering these nulls out at the source, i.e. in the SQL query.
By adding something like the following in the WHERE clause.
WHERE ... -- existing conditions
AND TheFieldOfInterest IS NOT NULL

Exactly as mjv already mentioned, you want to tell MySQL to skip over rows that have a NULL value in a particular column. As it stands in your question 'When a null value is read, I need the MySQL to read the next record.' : This is exactly what MySQL will do when you tell it not to include NULLs in the result set by specifying the WHERE condition.
Have fun hacking :)

In php you can use the is_null() function to detect whether a variable is null or not
$result = mysql_query("SELECT foo FROM bar;");
while($values = mysql_fetch_assoc($result))
{
if (is_null($values["foo"]))
continue; //Skip processing of this row
echo "Data: ".$values["foo"];
}

I agree that you shouldn't query all data and then filter the result set on the mysql-client (your php script). But: done that, but I "just" want to know another way :DThere's nothing wrong with being curious. And: More power to PDO and SPL, esp. FilterIterator in this case.
class ElementIssetFilter extends FilterIterator {
protected $index;
public function __construct(Iterator $iter, $index) {
parent::__construct($iter);
$this->index = $index;
}
public function accept() {
$c = $this->current();
return isset($c[$this->index]);
}
}
$pdo = new PDO('mysql:host=localhost;dbname=test', 'localonly', 'localonly');
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
// testtable and -data
$pdo->exec("CREATE TEMPORARY TABLE foo (id int auto_increment, v varchar(16), primary key(id))");
$pdo->exec("INSERT INTO foo (v) VALUES ('1'), (null), ('3'), ('4'), (null), ('6')");
$result = $pdo->query('SELECT id,v FROM foo');
$iter = new IteratorIterator($result);
$filterIter = new ElementIssetFilter($iter, 'v');
foreach( $filterIter as $e) {
echo $e['id'], " ", $e['v'], "\n";
}
$filterIter will act like $result, except that rows with NULL values in ['v'] will be filtered out. You don't have to change the "consuming" code, i.e. the same foreach-loop (or function/method call or whatever) would work with $result instead of $filterIter.

Related

Insert NULL into database with pdo

in the database I'm working with, there's a table named "packets", in this table there are columns like "id", "userid" etc. and a column named "usage"(I know its a poor choice of name cause usage is a reserved word, but sadly I may not change anything in the table), the type of this column is enum with 3 values("education", "study" and "advanced training") with "education" as default-value and the value can be NULL.
I wrote a class Packet with getters/setters like set_usage($usage)/get_usage() and a class Packet_dao for accessing database using pdo:
class Packet_dao {
private m_insert_query;
...
public function persist($data)
{
$query = $this->m_insert_query;
try
{
$stmt = $this->bind_param($data, $query);
$stmt->execute();
return true;
}
catch (PDOException $ex)
{
$this->m_error_message = $ex->getMessage();
return false;
}
}
private function bind_param($packet, $query)
{
$stmt = $this->m_pdo->prepare($query);
$stmt->bindParam(':userId', $packet->get_user_id());
...
$stmt->bindParam(':usage', $packet->get_usage());
return $stmt;
}
insert query would looks like
INSERT INTO packets (userId, number, ..., `usage`)
VALUES (:userId, Coalesce(:number, default(number)), Coalesce(:usage, default(`usage`)))
so if I want to add a packet into db, the code would looks like:
$packet = new Packet();
$packet_dao = new Packet_dao();
$packet->set_stuff("stuff");
$packet_dao->persist($packet);
so far, so good, everything is working fine.
now, another usage-case "fullversion" should be added, and instead of adding a new value to the enum, they decided to use NULL as value of usage for packets which are full version. Now I get a problem: when I try to set value for usage using $packet->set_usage(NULL), it will be interpreted as the same as if the value isn't set and the default value("education") will be set in this case. What should I do?
apparently, the 2nd parameter of Coalesce() force it to take the default value when nothing is set (or NULL), after I changed Coalesce(:usage, default(usage)) into :usage. It worked

Check if table exist using PDO

Hello all decided to begin learning PDO. However i'm having trouble creating a function to check if a table exists in my db.
Each individual item has there own table in which the table name is ($id).
<?php
include_once('config.php');
include_once('simple_html_dom.php');
$html = file_get_html('http://localhost:8888/CDOnline%20Online.html');
foreach($html->find('div.product-stamp-inner') as $content) {
$detail['itemid'] = $content->find('a',0)->href;
$detail['itemid'] = substr($detail['itemid'], 40, 6);
if (strpos($detail['itemid'], "?") !== false) {
$detail['itemid'] = substr($detail['itemid'], 0, 5);
}
$id = $detail['itemid'];
tableExists($dbh, $id);
}
function tableExists($dbh, $id)
{
//check if table exists
}
$dbh = null;
?>
I've tried to scour the forums in search of an answer but came up empty handed. The only thing that got me close to my answer was:
function tableExists($dbh, $id)
{
$results = $dbh->query("SHOW TABLE LIKE `$id`");
if(count($results)>0){echo 'table exists';}
}
But that just says all tables exists, when half of the tables don't exist.
Edit:The table should exist if there is 1 or more rows.
You are using backtics around $id. Change it to single quotes. Like this:
"SHOW TABLES LIKE '$id'"
Further note that the statement count($results)>0 will not work. You'll have to use $results->rowCount() instead.
Fxing both errors will give you the following function:
function tableExists($dbh, $id)
{
$results = $dbh->query("SHOW TABLES LIKE '$id'");
if(!$results) {
die(print_r($dbh->errorInfo(), TRUE));
}
if($results->rowCount()>0){echo 'table exists';}
}
SHOW TABLES... is MySQL dialect and will fail under pretty much any other DB engine. This is certainly not the definitive answer to portable table detection.
The closest to portable you could get would be to check whether SELECT * FROM $table yields an error,
or similar methods discussed here
If your need is simply to create a table if it does not exist, you can use:
CREATE TABLE IF NOT EXISTS $table ($field, ...)
You might want to name your tables in lower case to work around this bug if your DB is located on a Windows MySQL server, though.
This is posted simply if anyone comes looking for this question. Even though its been answered a bit.
if ($con->query(
"SHOW TABLES LIKE '" . $table . "'"
)->rowCount() > 0
or die("No table set")
){
With this I just push the else condition into or. And for my needs I only simply need die. Though you can set or to other things. Some might prefer the if / else if / else. Which is then to remove or and then supply if / else if / else.
Or if I was to redo the function:
function tableExists($dbh, $id){
if ($dbh->query(
"SHOW TABLES LIKE '" . $id . "'"
)->rowCount() > 0
or die(print_r($dbh->errorInfo(), TRUE))
){
echo 'table exists';
}
}
Did not test the redo, though it should work the same as the code I have used before. Just in function.
This seems like the simplest way to do this. You pass this function an array with the pdo object you have already created.
$db['pdo']=new PDO('mysqlconnectiongoeshere');
$db['table']='tabletobechecked';
function is_table($db){
$is_table=$db['pdo']->query("SHOW TABLES LIKE '".$db['table']."'");
return$is_table->rowCount();
}
This way if the table exists this function returns a '1' and if it doesn't exist this function returns a '0';
So you can use it like this:
if(is_table($db)){
echo"The table".$db['table']." exists.";
}else{
echo"The table".$db['table']." does not exist.";
}
private function doesTableExist($table)
{
try {
$this->db->query("DESC $table");
} catch (Exception $e) {
return false;
}
return true;
}
Just use good old row count. There must be a result if table exist.
$sql ="SELECT count(*) FROM [table name]";
$sql_result = $this->db_mssql->prepare($sql);
$sql_result->execute();
$sql_result->setFetchMode(PDO::FETCH_ASSOC);
$my_res = $sql_result->fetchAll();
if($my_res){
echo 'table exists';
}

Basic mysqli select

I have a select statement where I want to get all rows from a table but seem to be having a mental blockage - this should be elementary stuff but can't seem to get it working.
There are only two rows in the table 'postage_price' - and two columns : price | ref
Select statement is as follows:
$get_postage="SELECT price FROM postage_price ORDER BY ref DESC";
$get_postage_result=mysqli_query($dbc, $get_postage) or die("Could not get postage");
while($post_row=mysqli_fetch_array($dbc, $get_postage_result))
{
$post1[]=$post_row;
}
I am then trying to echo the results out:
echo $post1['0'];
echo $post1['1'];
this is not showing anything. My headache doesn't help either.
while($post_row = mysqli_fetch_array($dbc, $get_postage_result))
{
$post1[] = $post_row['price'];
}
As you see: $post_row in this line: = mysqli_fetch_array($dbc, $get_postage_result) is an array. You are trying to save the whole array value to another array in a block. :)
EDIT
while($post_row = mysqli_fetch_array($get_postage_result))
...
You have $post1[]=$post_row; and $post_row is itself an array. So you can access post data with following: $post1[NUMBER][0] where NUMBER is a $post1 array index and [0] is 0-index of $post_row returned by mysqli_fetch_array.
Probably you wanted to use $post1[]=$post_row[0]; in your code to avoid having array of arrays.
You are passing 1 and 0 as string indexes, this would only work if you had a column called 0 or 1 in you database. You need to pass them as numeric indexes.
Try:
print_r($post1[0]);
print_r($post1[1]);
or
print_r($post['price']);
print_r($post['ref']);
with all your help I have found the error - it is in the mysqli_fetch_array where I had the $dbc which is not required.
$get_postage="SELECT price FROM postage_price ORDER BY ref DESC";
$get_postage_result=mysqli_query($dbc, $get_postage) or die("Could not get postage");
while($post_row=mysqli_fetch_array($get_postage_result))
{
$post1[]=$post_row['price'];
}
instead of:
$get_postage="SELECT price FROM postage_price ORDER BY ref DESC";
$get_postage_result=mysqli_query($dbc, $get_postage) or die("Could not get postage");
while($post_row=mysqli_fetch_array($dbc, $get_postage_result))
{
$post1[]=$post_row['price'];
}
Bad day for me :(
Thanks all
If something does not work in a PHP script, first thing you can do is to gain more knowledge. You have written that
echo $post1['0'];
echo $post1['1'];
Is showing nothing. That could only be the case if those values are NULL, FALSE or an empty string.
So next step would be to either look into $post1 first
var_dump($post1);
by dumping the variable.
The other step is that you enable error display and reporting to the highest level on top of your script so you get into the know where potential issues are:
ini_set('display_errors', 1); error_reporting(~0);
Also you could use PHP 5.4 (the first part works with the old current PHP 5.3 as well, the foreach does not but you could make query() return something that does) and simplify your script a little, like so:
class MyDB extends mysqli
{
private $throwOnError = true; # That is the die() style you do.
public function query($query, $resultmode = MYSQLI_STORE_RESULT) {
$result = parent::query($query, $resultmode);
if (!$result && $this->throwOnError) {
throw new RuntimeException(sprintf('Query "%s" failed: (#%d) %s', $query, $this->errno, $this->error));
}
return $result;
}
}
$connection = new MyDB('localhost', 'testuser', 'test', 'test');
$query = 'SELECT `option` FROM config';
$result = $connection->query($query);
foreach ($result as $row) {
var_dump($row);
}

Is it possible to call a PHP function from an SQL query?

Say there is a special PHP function foo($number) that returns double the value of its input. Further, say there is a table that contains the column "number." Is there a way to have the PHP function and SQL query to run together so that I would get the following:
Number | Double
================
1 | 2
5 | 10
While in this simple example column Double can easily be implemented within the SQL statement, answers should cover the more general case of calling any PHP function, as there are many operations that are difficult to impossible in SQL but easy in PHP.
No, since the query results come straight from MySQL. You can apply the function to the result set after you execute your query, either by using a loop or by applying your function to the results using array_map() function.
Depending on what you're actually trying to achieve it might be possible to decouple the data source and the consumer a bit, enough to put another component between them.
Let's start with
<?php
$result = getData($pdo); // a)
doSomething($result); // b)
function getData($mysql) {
return mysql_query('SELECT x FROM soTest', $mysql);
}
function doSomething($result) {
while ( false!==($row=mysql_fetch_assoc($result)) ) {
echo ' ', join(', ', $row), "\n";
}
echo "----\n";
}
There's very little you can do to alter a mysql result resource. And doSomething() does nothing more than iterating over the result set. It does nothing that is special to a mysql result set, yet it allows nothing else but this exact resource type by using mysql_fetch_xyz().
Let's try this again using PDO (PDO_MYSQL).
$result = getData($pdo);
doSomething($result);
function getData($pdo) {
return $pdo->query('SELECT x FROM soTest');
}
function doSomething(PDOStatement $result) {
while ( $row=$result->fetch(PDO::FETCH_ASSOC) ) {
echo ' ', join(', ', $row), "\n";
}
echo "----\n";
}
That didn't change much. Some names but essentially this is the same. But PDOStatement implements the Traversable interface, so you can use it directly with foreach.
$result = getData($pdo);
doSomething($result);
function getData($pdo) {
return $pdo->query('SELECT x FROM soTest', PDO::FETCH_ASSOC);
}
function doSomething($traversable) {
foreach( $traversable as $row ) {
echo ' ', join(', ', $row), "\n";
}
echo "----\n";
}
That's a game changer... We can pass any traversable/iterator to doSomething() and it still does more or less the same thing as before.
Now we can put something "between" getData() and doSomething(). This something takes an inner iterator (like getData() provides in the form of an PDOStatement) and behaves itself like an iterator (so DoSomething() can use it) returning all elements of its inner iterator but modifying some elements.
I chose to extend FilterIterator for this example for no particular reason. You need php 5.3+ to run this demo since it uses an anonymous function:
<?php
$pdo = initDemo();
echo "#1: passing \$result\n";
$result = getData($pdo); // a)
doSomething($result); // b)
echo "#2: passing ModifyIterator\n";
$result = getData($pdo); // exact same as a)
$result = new ModifyIterator($result, null, function($e) {
$e['y'] = '/' . ($e['x'] * 2) .'/';
return $e;
});
doSomething($result); // exact same as b)
function getData($pdo) {
return $pdo->query('SELECT x FROM soTest', PDO::FETCH_ASSOC);
}
function doSomething($traversable) {
foreach($traversable as $row) {
echo ' ', join(', ', $row), "\n";
}
echo "----\n";
}
class ModifyIterator extends FilterIterator {
protected $fnAccept, $fnModify;
public function __construct($it, $fnAccept, $fnModify) {
// todo: test parameters!
$this->fnAccept = $fnAccept;
$this->fnModify = $fnModify;
if ( !($it instanceof Iterator) ) {
$it = new IteratorIterator($it);
}
parent::__construct($it);
}
public function accept() {
return $this->fnAccept ? $this->fnAccept(parent::current()) : true;
}
public function current() {
if ( $this->fnModify ) {
$fn = $this->fnModify;
return $fn(parent::current());
}
return parent::current();
}
}
function initDemo() {
$pdo = new PDO('mysql:host=localhost;dbname=test', 'localonly', 'localonly');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('CREATE TEMPORARY TABLE soTest (x int auto_increment, primary key(x))');
$pdo->exec('INSERT INTO soTest VALUES (),(),(),(),()');
return $pdo;
}
prints
#1: passing $result
1
2
3
4
5
----
#2: passing ModifyIterator
1, /2/
2, /4/
3, /6/
4, /8/
5, /10/
----
The important part is that ModifyIterator forces very little particular behaviour on the inner iterator (e.g. you can still use an unbuffered query without the need to transfer all the data into the php process' memory at once) and that both getData() and doSomething() are left unchanged.
One way would be to fetch the results into objects:
class NumberDoubler
{
public $number;
public function __construct()
{
$this->number *= 2;
}
}
$pdo = new PDO('mysql:host=localhost;dbname=db_name', 'uname', 'pword');
$stmnt = $pdo->query('SELECT number FROM db_table');
$result = $stmnt->fetchAll(PDO::FETCH_CLASS, 'NumberDoubler');
print_r($result);
The result will be an array of objects with '$number' doubled. Of course, iteration will still be done "behind the scenes", and the manual warns, "Using this method to fetch large result sets will result in a heavy demand on system and possibly network resources."
See also PDOStatement::setFetchMode().
You don't need to use PHP. You can just execute a regular SQL statement as follows.
SELECT number, number * 2 FROM tablename;
//Your query would prob be like so.
$query = mysql_query("SELECT (number * 2) as double,number FROM table");
echo '<table>';
while($row = mysql_fetch_assoc($query))
{
echo sprintf('<tr><td>%d</td><td>%d</td></tr>',$row['number'],$row['double']);
}
echo '</table>';
I think I understand your question.
It sounds as though you want to pull a number from a database and double it through a php function.
I would first learn to write the php function... Check this out for a tutorial.
Once you have that down, pull your number from the database. Here is a tutorial on how to do that.
This is all about learning. Me posting code for you to just copy doesn't help you learn and is basically a waste of my time. Best of luck.
It depends on what the function is doing. Basic stuff like arithmetic can be done with SQL directly. Otherwise, you can loop over the result array and run the function in the particular field, e.g.:
$rows = array();
foreach(($row = mysql_fetch_assoc($result))) {
$row['double'] = func($row['number']);
rows[] = $row;
}
No, it's impossible to use php function() and sql together
However, you can get results from SQL database and apply whatever PHP function on it

How to Set a Value to NULL when using Zend_Db

When performing UPDATE and INSERT queries using Zend_Db, I frequently need to set values equal to NULL (not ''). However, the default behavior of Zend_Db::insert() and Zend_Db::update() seems to be that values that are empty are translated into empty strings ('') and put into the database as such.
Does anyone know of way to actually force a NULL value to go into fields if the value is empty in php?
Try setting the affected fields to: new Zend_Db_Expr('NULL')
I've always just been able to do this using PHP's null:
$toUpdate = array('nullValue' => null, 'otherValue' => 'something');
Zend_Db::update($table, $toUpdate, $where);
As Johrn I was able to do this with PHP's null value:
$value = null;
$what = array($columnName => $value);
$where = $this->_dbTableName->getAdapter()->quoteInto('Id = ?', $dbRecord->Id);
$this->_dbTableName->update($what, $where);
but encountered situations where the database itself had the column set to NOT NULL and in such cases the value was indeed converted to either empty string or in case of FLOATs to 0.00. I guess INT column would end up as 0 ;-)
While using Zend 2.4.7 for those who may be visiting this issue, I was able to use this with William Lannen's answer providing some inspiration. Assuming getTable() returns a Zend\Db\TableGateway object:
public function fetch()
{
$data['column_name1 = ?'] = 'column_value';
$data[] = new \Zend\Db\Sql\Predicate\IsNull('column_name2');
$resultSet = $this->getTable()->select($data);
if (0 === count($resultSet) {
return 'SomeExpectationOrException';
} else {
return $resultSet;
}
}

Categories