PDO - check if row was updated? - php

Other people have asked this question, but mine is a little more specific.
I have this query:
$sql = "UPDATE table SET option=? WHERE number=?";
$q = $conn->prepare($sql);
$q->execute(array($option, $number));
$q->setFetchMode(PDO::FETCH_BOTH);
echo $q->rowCount();
If the WHERE number already exists and the SET option is same, $q->rowCount() equals 0
If the WHERE number doesnt exist and the row does not update, $q->rowCount() equals 0
How can I distinguish between these non-updates?

On recent PHP versions, it's controlled by the PDO::MYSQL_ATTR_FOUND_ROWS attribute.
When set to true, according to the doc, the effect is:
Return the number of found (matched) rows, not the number of changed rows.

Will be better check before if exists? I use a common function for this in my miniclass for manage PDO, but i dont know if is the best solution because make one query more...
function checkExistsInDatabase($id, $table, $where = null){
// Connect
$Database = Database::connect();
// Query
$sql = "SELECT id
FROM $table
WHERE id = :id $where
LIMIT 1";
$params = array(
':id' => array(
'value' => $id,
'type' => 'int'
)
);
$q = $Database->query($sql, $params);
// Ha encontrado algo?
$resultados = $Database->fetchArray($q);
if(count($resultados) === 1){
return true;
}else{
return false;
}
}

You can try using REPLACE which work's like insert but if the row already exists its first deleted and then inserted. This has overwork from mysql side

Add this:
$db = new PDO($dsn, $username, $password, array(PDO::MYSQL_ATTR_FOUND_ROWS => true));
to the first "try {" part of your databasefunctions.php file

Related

How to check if column equals a value and do somthing if true? [duplicate]

This question already has answers here:
Single result from database using mysqli
(6 answers)
Closed 2 years ago.
I am trying to write a function that will check for a single value in the db using mysqli without having to place it in an array. What else can I do besides what I am already doing here?
function getval($query){
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
$result = $mysqli->query($query);
$value = $mysqli->fetch_array;
$mysqli->close();
return $value;
}
How about
$name = $mysqli->query("SELECT name FROM contacts WHERE id = 5")->fetch_object()->name;
The mysql extension could do this using mysql_result, but mysqli has no equivalent function as of today, afaik. It always returns an array.
If I didn't just create the record, I do it this way:
$getID = mysqli_fetch_assoc(mysqli_query($link, "SELECT userID FROM users WHERE something = 'unique'"));
$userID = $getID['userID'];
Or if I did just create the record and the userID column is AI, I do:
$userID = mysqli_insert_id($link);
Always best to create the connection once at the beginning and close at the end. Here's how I would implement your function.
$mysqli = new mysqli();
$mysqli->connect(HOSTNAME, USERNAME, PASSWORD, DATABASE);
$value_1 = get_value($mysqli,"SELECT ID FROM Table1 LIMIT 1");
$value_2 = get_value($mysqli,"SELECT ID FROM Table2 LIMIT 1");
$mysqli->close();
function get_value($mysqli, $sql) {
$result = $mysqli->query($sql);
$value = $result->fetch_array(MYSQLI_NUM);
return is_array($value) ? $value[0] : "";
}
Here's what I ended up with:
function get_col($sql){
global $db;
if(strpos(strtoupper($sql), 'LIMIT') === false) {
$sql .= " LIMIT 1";
}
$query = mysqli_query($db, $sql);
$row = mysqli_fetch_array($query);
return $row[0];
}
This way, if you forget to include LIMIT 1 in your query (we've all done it), the function will append it.
Example usage:
$first_name = get_col("SELECT `first_name` FROM `people` WHERE `id`='123'");
Even this is an old topic, I don't see here pretty simple way I used to use for such assignment:
list($value) = $mysqli->fetch_array;
you can assign directly more variables, not just one and so you can avoid using arrays completely. See the php function list() for details.
This doesn't completely avoid the array but dispenses with it in one line.
function getval($query) {
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
return $mysqli->query($query)->fetch_row()[0];
}
First and foremost,
Such a function should support prepared statements
Otherwise it will be horribly insecure.
Also, such a function should never connect on its own, but accept an existing connection variable as a parameter.
Given all the above, only acceptable way to call such a function would be be like
$name = getVal($mysqli, $query, [$param1, $param2]);
allowing $query to contain only placeholders, while the actual data has to be added separately. Any other variant, including all other answers posted here, should never be used.
function getVal($mysqli, $sql, $values = array())
{
$stm = $mysqli->prepare($sql);
if ($values)
{
$types = str_repeat("s", count($values));
$stm->bind_param($types, ...$values);
}
$stm->execute();
$stm->bind_result($ret);
$stm->fetch();
return $ret;
}
Which is used like this
$name = getVal("SELECT name FROM users WHERE id = ?", [$id]);
and it's the only proper and safe way to call such a function, while all other variants lack security and, often, readability.
Try something like this:
$last = $mysqli->query("SELECT max(id) as last FROM table")->fetch_object()->last;
Cheers

Exclude a field from a SELECT * FROM $table

I need to exclude a field 'password' from a SELECT * FROM $table; where $table is a PHP variable.
Only one of the four posible tables has a 'password' field.
Here is what I have:
function myData($table)
{
include "conf.php";
$con = mysqli_connect($host, $user, $password, $db);
$sql = "SELECT * FROM $table;";
$resul = mysqli_query($con, $sql);
return $resul;
}
Any ideas?
EDIT: This is how I treat the data returned:
$resulFields = myFields($table);
$resulData = myData($table);
while ($fields = mysqli_fetch_array($resulFields, MYSQLI_ASSOC)) {
$field = $fields['Field'];
$header .= "<th>$field</th>";
while ($data_array = mysqli_fetch_array($resulData, MYSQLI_ASSOC) ) {
$body .= "<tr id='$data_array[id]'>";
foreach ($data_array as $data){
$body .= "<td>$data</td>";
}
}
}
Sorry if it's a little bit messy, I'm just starting to learn programming.
I understand that you're wanting to have a single PHP function that will return all the results in a given table. Perhaps instead of returning the $resul variable and parsing the data after the return, you should parse it into an associative array prior to returning it. You can try something like this:
function myData($table) {
include "conf.php";
$con = mysqli_connect($host, $user, $password, $db);
$sql = "SELECT * FROM {$table}";
$resul = mysqli_query($con, $sql);
$row = $resul->fetch_assoc();
unset( $row['password'] );
return $resul;
}
Though I feel it's important to note that in the interests of proper coding practices and single responsibility, you should have specific data access functions for each query you wish to run. I don't recommend having a single function that just returns everything from a table. Functions should also be named such that you know what they're doing. "myData" is very non-descriptive and as such a very poor name for a data access function.
Also, if you're going to name a variable $resul, just go ahead and type the "t" and name it $result FFS.
In the foreach loop, get the key and the data from the array. (The current code is getting only the data.)
Inside the foreach loop, do a conditional test on the value of key.
If the value of the key matches "password", then skip over outputting anything for that element of the array. If it doesn't match key, then output it (like the current code is doing.)
Look at the alternative syntax for foreach:
References: http://php.net/manual/en/control-structures.foreach.php
And for simple conditional tests
Reference: http://php.net/manual/en/control-structures.if.php
Consider whether you want to match "password", "PASSWORD", "Password", etc. You might want a case insensitive match.
Maybe you can do something like this:
function myData($table) {
include "conf.php";
$con = mysqli_connect($host, $user, $password, $db);
$sql = "SELECT field1, field2";
if ($table == "TABLE_WITH_PASSWORD") {
$sql.=",password";
}
$sql.=" FROM $table;";
$resul = mysqli_query($con, $sql);
return $resul;
}
Obviously the best bet is to select what you do want:
SELECT id, name, whatever FROM $table
Hopefully I'm not going down the wrong path, but here is one way other than querying for the fields and removing the password:
$columns['tableA'] = array('id', 'name', 'whatever');
$columns['tableB'] = array('id', 'user', 'something');
Then do:
$select = implode(',', $columns[$table]);
$sql = "SELECT $select FROM $table";
IMO i think the simplest way in this case is to use special case for php
function myData($table) {
include "conf.php";
$con = mysqli_connect($host, $user, $password, $db);
if($table == "special_case_table"){
$sql = "SELECT col1, col2, col3 FROM special_case_table;"; //except "password" column
}
else $sql = "SELECT * FROM $table;";
$resul = mysqli_query($con, $sql);
return $resul;
No need more function or go search in INFORMATION_SCHEMA of database to find column password.

php prepared statement and transictions , function

I am trying to write a function that is supposed to receive any MySQL statement and apply it,
The basic idea is not to repeat needed code to write to Database, well what is needed to connect to Database is creating new PDO object, starting a transaction and preparing a statement, binding values to it, executing it,
so every time I want to access the Database I don't have to repeat these steps,
Here is a function that does that :
==============================================================================================
protected function applyQuery($statement, $bindparameters , &$values , $selectStatement, &$result){
try{
$dbh = DataBase::setConnection();// new PDO("MySQL= .....");
$dbh->beginTransaction();
$stmt = $dbh->prepare($statement);
if($bindparameters == true){
foreach($values as $key => $value){
$stmt->bindValue($key, $value);
}
}
$stmt->execute();
$dbh->commit();
if($selectStatement == TRUE){
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
}catch (PDOException $e){
$dbh->rollBack();
throw DataBase::$Errors[0];
}
}
============================================================================================
$statement = the desired statement (e.g 'SELECT * from users WHERE username = :username')
$bindparameters = do we need to bind values (in this examples yes) so its value TRUE
&$values = array by reference in this case equals = (':username' => 'User');
$selectStatement = tells if using SELECT in statement ,in this case TRUE
$result = array by reference in this case the final fetch result will be stored in it
so in this example we get the following call to the function :
applyQuery('SELECT * from users WHERE username = :username', TRUE ,
array(':username' => 'User') , TRUE , result )
My question is : will this code work ? is the logical sequence of what it does and should do make sense ? whats the difference between $stmt->execute and $dbh->commit ? is omitting any line will cause failure to achieve the desired result
Please understand that I did lookup what is PDO and read a lot but unable to answer these questions!

Delete row not working in joomla

I'm creating a component in joomla and I'm having some problems using the database, specifically to delete rows. The code below is what I'm using
$db = JFactory::getDbo();
$query = $db->getQuery(true);
// delete if this date already exists for this user
$conditions = array(
$db->quoteName('userid') . '='.$array['userid'],
$db->quoteName('date') . '='.$date
);
$query->delete($db->quoteName('#__timereport_schedule'));
$query->where($conditions);
$db->setQuery($query);
$result = $db->execute();
So what I'm trying to do here is delete the rows that match the given userid and date, fairly simple. However it ends up not affecting the database. I know the variables $array['userid'] and $date are correct because the same are used later in the same function to do a insert (it's supposed to delete the record if it exists and make a new one) and the insert works fine which means I end up with duplicate entries.
example row that was succesfully inserted:
(userid, date, starttime, endtime, id, enddate, leave, days)
VALUES
(456, '2013-01-01', '08:00:00', '16:00:00', 448, '2013-01-01', '3', '["Tue"]')
with:
$query = $db->getQuery(true);
$columns = array('userid', 'date', 'starttime', 'endtime', 'id', 'leave');
$values = array("'".$array['userid']."'", "'".$date."'", "'".$array['starttime']."'", "'".$array['endtime']."'", "'null'", "'".$array['leave']."'");
$query
->insert($db->quoteName('#__timereport_schedule'))
->columns($db->quoteName($columns))
->values(implode(',', $values));
$db->setQuery($query);
try {
$result = $db->execute();
} catch (Exception $e) {
return $e;
}
What am I missing? I followed the http://docs.joomla.org/Inserting,_Updating_and_Removing_data_using_JDatabase#Deleting_a_Record example to create this query.
The below code should work since I've defined sample date and userid. Also, and most importantly, you should be quoting the data (much more important than the db fields, btw):
$array['userid'] = 127;
$date = date("Y-m-d H:i:s");
$db = JFactory::getDbo();
$query = $db->getQuery(true);
// delete if this date already exists for this userv
$conditions = array(
$db->quoteName('userid') . '='.$db->quote($array['userid']),
$db->quoteName('date') . '='.$db->quote($date)
);
$query->delete($db->quoteName('#__timereport_schedule'));
$query->where($conditions);
try {
$db->setQuery($query);
$result = $db->execute();
}
catch (RuntimeException $e){
echo $e->getMessage();
}
// for testing you can echo the query as
echo $db->replacePrefix($query);
If $array['userid'] is not defined or empty, and $date is not defined, the query most certainly would throw an error in this example
At the end, add echo $query;. This should print to the screen the SQL query that is actually being run. Post that so we can see the query, since this will help see what could be wrong.
Also, in many cases, Joomla redirects after saves to prevent a page refresh from resubmitting data. So it can be helpful to add an exit(); statement after the echo to actually see what it is echoing.
(Though as I type this, I'm guessing that the date needs to be quoted.)
Use below code after setQuery
$db->setQuery($query);
$result = $db->query();

PHP with sqlsrv_num_rows

I'm attempting to execute a query of a SQL Server database, looking at a many to many relationship. I link the table I want the rows from with the relationship table, and plug in the unique id, in this case the $guid.
The query is functional, sometimes. It will work, and then I switch out solely the $guid for another one, and it fails, even though I'm staring at the table and it has values associated with that new $guid.
<?php
$guid = '{893C7BF8-E8C5-41D5-9C61-A72CF62DDBA8}';
// Connect to Database
$server = "###($#";
$connectionSettings = array("Database"=>"db", "UID"=>"user", "PWD"=>"pword");
$connection = sqlsrv_connect($server, $connectionSettings);
if (!$connection){
die("Failed Connection");
}
// Prepare and Execute Query
$sql = "SELECT *
FROM STREAMS.ATTACHMENTS a INNER JOIN STREAMS.RELATTACHMENTS ra
ON a.ROWGUID = ra.ATTACHMENT_GUID
WHERE ra.FEATURE_GUID = '" . $guid . "'";
$results = sqlsrv_query($connection, $sql);
$rowCount = sqlsrv_num_rows( $results );
if ($rowCount === false)
echo "failure";
else
echo $rowCount;
while($row = sqlsrv_fetch_array($results)){
echo "loop";
}
?>
Even stranger, the output to this code is the following:
failurelooploop
So that implies that the sqlsrv_num_rows command counted no rows in the result... but it also implies that the same results set has 2 rows, since the while loop went around twice.
Can anybody explain this funky behavior?
Thanks.
I will bet that you have some sort of error: sqlsrv_num_rows will return FALSE if something goes wrong. You can get the error output through:
// probably don't want this in production.
print_r( sqlsrv_errors());
I'll guess the cause has to do with your guid column, but I can't be sure. :-)
Oh, and unless you need the number of rows, don't use it. Use do... while instead:
$row = sqlsrv_fetch_array($results);
if($row)
{
do{
echo "loop";
} while( $row = sqlsrv_fetch_array( $results ) );
}
else
{
// No results found
// you can output print_r( sqlsrv_errors() ); here
}
This error shows for cursor type SQLSRV_CURSOR_FORWARD & SQLSRV_CURSOR_DYNAMIC . my personal preference is not to use it. if you still want to use it pass extra parameter to query function like :
$stmt = sqlsrv_query( $connection, $sql, array(), array( "Scrollable" => 'keyset' ));
// $stmt = sqlsrv_query( $connection, $sql, array(), array( "Scrollable" => 'dynamic' ));
// $stmt = sqlsrv_query( $connection, $sql, array(), array( "Scrollable" => 'static' ));
check more : https://msdn.microsoft.com/en-us/library/hh487160.aspx
-- http://php.net/manual/en/function.sqlsrv-query.php

Categories