How do I remove a row from mysql immediately after calling it? - mysql

Basically, I have a mysql database where every time I get a row, I want to delete it from the database (after reading its information).
I know I could do something like
$result = mysql_query(" SELECT <some row> FROM table ");
$row = mysql_fetch_array($result);
$id = $row["id"];
mysqli_query(" DELETE FROM table WHERE id=$id");
but now it seems I have two queries going on. Is there a command to tell mysql that I want the row deleted as soon as it gives me the information? I imagine that'd save time and resources.
In my head, it looks like
$result = mysql_query(" SELECT <some row> FROM table THEN DELETE ");
EDIT additional information: I wish to use the SELECTed information after deleting the row. To put it simply, I only want one instance of the information to exist at any give time; it would be as if I were only "moving" a physical copy of the information, so that when it is put on a device/what have you, it is no longer in the table since there is only one copy.
Sorry if my understanding of mysql is rough -- I'm pretty new to it :P

I don't know why you need it but you can use a stored procedure for that:
DELIMITER $$
CREATE PROCEDURE select_and_delete(IN aid INT)
BEGIN
SELECT * FROM table1 WHERE id = aid;
DELETE FROM table1 WHERE id = aid;
END$$
DELIMITER ;
Here is SQLFiddle demo.
mysql_* extension is deprecated, therefore use prepared statements and mysqli or PDO.
Your php code using PDO might look like
$id = 1;
try {
$db = new PDO('mysql:host=localhost;dbname=test;charset=UTF8', 'user', 'userpwd');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$query = $db->prepare("CALL select_and_delete(?)");
$query->execute(array($id));
$result = $query->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo "Exception: " .$e->getMessage();
$result = false;
}
$query = null;
$db = null;
//do whatever you need to do with your resultset
var_dump($result);
Following a rather simplified table structure (with the only column id) presented in SQL Fiddle example if you call it with $id=1 you'll you'll get in $result:
array(1) {
[0]=>
array(1) {
["id"]=>
int(1)
}
}

You'll need to add a timestamp field (with default as CURRENT_TIMESTAMP) to be able to tell when the row was added.
Then you can run the following MySQL query.
DELETE FROM `table` WHERE `timestamp` > DATE_SUB(NOW(), INTERVAL 0 SECOND);
You will need to run this as a cron job though. AFAIK it can't be done in MySQL alone.

Related

How to catch fails in pdo batch insert

I have this code to insert data from a CSV file to the database. Since, the CSV might have thousands of records, I am trying to implement a batch insert as follows.
$this->_connection->beginTransaction();
$sql = "INSERT INTO dbtable (col1,col2) VALUES (:value1,:value2)";
$stmt = $this->_connection->prepare($sql);
foreach ($requestArray['csv'] as $data) {
$stmt->bindParam(':value1', $data['csvCol1']);
$stmt->bindParam(':value2', $data['csvCol2']);
$stmt->execute();
}
$this->_connection->commit();
The variable $requestArray['csv'], holds all the record of the CSV post request. This code seems to be working as it should. Though, I am trying to improve it, because I want to let the user know how many records failed to insert on the database and if it is possible to show which records failed. Assume a duplicate key, or invalid data or generally any error that might come from this procedure.
PDOStatement::execute() will return false on failure:
$this->_connection->beginTransaction();
$sql = "INSERT INTO dbtable (col1,col2) VALUES (:value1,:value2)";
$stmt = $this->_connection->prepare($sql);
foreach ($requestArray['csv'] as $data) {
$stmt->bindParam(':value1', $data['csvCol1']);
$stmt->bindParam(':value2', $data['csvCol2']);
if (!$stmt->execute()) {
// error processing goes here.
}
}
$this->_connection->commit();

While loop only stores one value from #row=$sth->fetchrow_array() perl

sub completecheckout {
$cryptedcard = md5_hex($cardnum . $salt);
$grabcart = qq~select pid from cart where uid='$cookievalue'~;
$dbh = DBI->connect($connectionInfo, $user, $passwd);
$sth = $dbh->prepare($grabcart);
$sth->execute();
while (#row = $sth->fetchrow_array()) {
$insert = qq~insert transaction (uid, pid, cctype, ccnum)
values ('$cookievalue', '$row[0]', '$cardtype',
'$cryptedcard')~;
$dbh = DBI->connect($connectionInfo, $user, $passwd);
$sth = $dbh->prepare($insert);
$sth->execute();
}
$select = qq~select * from registered where id in
(select uid from transaction
where uid='$cookievalue')~;
$dbh = DBI->connect($connectionInfo,$user,$passwd);
$sth = $dbh->prepare($select);
$sth->execute();
#userinfo = $sth->fetchrow_array();
print header;
print qq~<html><head><title>YAY</title></head><body><p>CHECK MYSQL<p><p>#row</p></body></html>~;
}
I am trying to parse through the table cart and insert all the items associated with the user into a transaction table when they click the final checkout button. The above code will only insert the last row into the transaction table.
Here is code that inserts more than once, but does not work because $product is empty every other time.
sub completecheckout {
$cryptedcard = md5_hex($cardnum . $salt);
$grabcart = qq~select pid from cart where uid='$cookievalue'~;
$dbh = DBI->connect($connectionInfo,$user,$passwd);
$sth = $dbh->prepare($grabcart);
$sth->execute();
#cart = $sth->fetchrow_array();
foreach $product (#cart) {
$insert = qq~insert transaction (uid, pid, cctype, ccnum)
values ('$cookievalue', '$product', '$cardtype',
'$cryptedcard')~;
$dbh = DBI->connect($connectionInfo,$user,$passwd);
$sth = $dbh->prepare($insert);
$sth->execute();
}
$select = qq~select * from registered where id in
(select uid from transaction
where uid='$cookievalue')~;
$dbh = DBI->connect($connectionInfo,$user,$passwd);
$sth = $dbh->prepare($select);
$sth->execute();
#userinfo = $sth->fetchrow_array();
print header;
print qq~<html><head><title>YAY</title></head><body><p>CHECK MYSQL<p><p>#userinfo</p></body></html>~;
}
Can anyone explain why this happens? I have been using while loops with fetchrow_array throughout my script to create tables linked to databases.
Firstly, you need to get into the habit of formatting your code better. It really helps following logic flow if the formatting imitates the logic.
Secondly, please turn on use strict and get used to declaring variables as close to their point of use as possible.
Thirdly, don't use global variables. Your subroutine uses $cardnum, $salt, $cookievalue and several other variables which are (presumably) defined outside of the subroutine. They should all be passed into the subroutine as parameters.
I know from previous conversations that you have no interest in learning Perl, you're just trying to get through a course that your college insists on. So I should make it clear that all of the advice above has nothing to do with Perl. That is all good general advice for any programming language.
Now, the specific problems.
You're creating a new $dbh any time you want to run a database query. Why not just connect once and then reuse that variable. A single $dbh can support multiple queries executing at the same time.
As Matt has pointed out in the comments, you are overwriting $sth. As I said above, a $dbh can support multiple concurrent queries, but each query needs its own statement handle. So you might do something like:
my $dbh = DBI->connect(...);
my $select_sth = $dbh->prepare($select_sql);
$select_sth->execute;
while (my #row = $select_sth->fetchrow_array) {
my $insert_sth = $dbh->prepare($insert_sql);
$insert_sth->execute;
}
Notice how I've a) reused the same $dbh and b) declared the $insert_sth within the loop so it's only available for the shorted possible amount of time.
If you were interested in Perl, I'd also show you how to make your code more efficient by using bind points in your SQL and passing extra parameters to execute(). I'd also recommend moving raw HTML out of your program and using a templating engine. But I strongly suspect you wouldn't be interested.

why codeigniter active record 'LIKE' not work in update query?

$array=array(
'amount'=>$this->input->post('netamt'),
'trandate'=>$billdate,
'crcode'=>$this->input->post('rcode')
);
$this->db->where('voucher',$this->input->post('billno'));
$this->db->like('code','16','after');
$this->db->update('tranachst',$array);
when display this query using
echo $this->db->last_query();
UPDATE `tranachst` SET `amount` = '717360', `trandate` = '2015-07-15', `crcode` = '311001' WHERE `voucher` = '15020'
here like query not working , why ?
Please Try This --
My Exmaple --
$this->db->where('faq_id', $id);
$this->db->where('question LIKE ', '%do%');
$this->db->update('admin_faqs', $data);
Your Example --
$array=array(
'amount'=>$this->input->post('netamt'),
'trandate'=>$billdate,
'crcode'=>$this->input->post('rcode')
);
$this->db->where('voucher',$this->input->post('billno'));
$this->db->where('code LIKE ', '16%');
$this->db->update('tranachst',$array);
In this code you don`t need to use after, before parameter please try this..
Some people have the same question, and until now i don't know why. but clearly CI didn't support active record like above.
you can use $this->db->query() or
function index(){
$this->load->database();
$data=array(
'userlogin'=>'test'
);
$this->db->where('userlogin','xx');
$this->db->where("email like 'xx'");
$q=$this->db->update('master_user',$data);
}
something like that work too.
the same question : CodeIgniter Active Record 'like' ignoring 'where'

MYSQL Prepared Statements Select Row_Count

I have a simple SQL Query:
$stmt = $db_main->prepare("SELECT id FROM user WHERE username=? AND mail=? LIMIT 1");
$stmt->bind_param('ss', $username, $mail);
$stmt->execute();
And I want to know, if it found an user. So I want to count the rows found.
I already tried to use rowCount (Not safe for SELECT) or num_rows or just looking if the result id is numeric (Which '' would not be, I hoped...)
There has to be an easy way to count the selected row, hasn't be?
Check number of rows returned with:
$stmt->num_rows;
Check for instance this site.
p.s.: added as per question in comment: use fetch() in order to get the next record.
...
$stmt->execute();
$stmt->bind_result($user_id); // access id
$stmt->store_result(); // optional: buffering (see below)
if ($data = $stmt->fetch()) {
do {
print("Id: " . $user_id);
} while ($data = $stmt->fetch());
} else {
echo 'No records found.';
}
Regarding store_result() from the documentation:
"You must call mysqli_stmt_store_result() for every query ..., if and only if you want to buffer the complete result set by the client ..."

Joomla Database - How to use LIMIT in getQuery?

I want to build the below query using joomla inbuilt database class.
SELECT *
FROM table_name
ORDER BY id DESC
LIMIT 1
This is the query I have built up to now.
$db =& JFactory::getDBO();
$query = $db->getQuery(true);
$query->select($db->nameQuote('*'));
$query->from($db->nameQuote(TABLE_PREFIX.'table_name'));
$db->setQuery($query);
$rows = $db->loadObjectList();
I don't know how to add the limit(LIMIT 1) to the query. Can someone please tell me how to do it? Thanks
Older than Joomla 3.0
$db = JFactory::getDBO();
$query = $db->getQuery(true);
$query->select('*')
->from($db->nameQuote('#__table_name'))
->order($db->nameQuote('id').' desc');
$db->setQuery($query,0,1);
$rows = $db->loadObjectList();
$db->setQuery function takes 3 parameters. The first one being the query, then the start, then the limit. We can limit records as shown above.
Newer than Joomla 3.0
setLimit(integer $limit, integer $offset)
If you want just one row
$query->setLimit(1);
Read more
This should work as well:
$query->setLimit(1);
Documentation: http://api.joomla.org/cms-3/classes/JDatabaseQueryLimitable.html
SetLimit doesn't work for me in Joomla 3.4.x, so try:
Within the model:
protected function getListQuery()
{
// Create a new query object.
$db = JFactory::getDBO();
$query = $db->getQuery(true);
// Select some fields
$query->select('*');
$query->from('#__your_table');
$this->setState('list.limit', 0); // 0 = unlimited
return $query;
}
Davids answer: https://joomla.stackexchange.com/questions/4249/model-getlistquery-fetch-all-rows-with-using-jpagination
Run that before the model calls getItems and it will load all the
items for you.
A few caveats with this.
You can also do this outside the model, so if for instance you were in
your view. You could do the following:
$model = $this->getModel(); $model->setState('list.limit', 0);
Sometimes you can do this too early, before the model's state has been
populated, which will cause the model to get rebuilt from the user
state after you have set the limit, basically overriding the limit.
To fix this, you can force the model to populate its state first:
$model = $this->getModel(); $model->getState();
$model->setState('list.limit', 0); The actual populateState method is
protected, so outside the model you can't call it directly, but any
call to getState will make sure that the populateState is called
before returning the current settings in the state.
Update: Just had to revisit this answer, and I can confirm, both the methods
setLimit & order are working if used as below.
$query->order($db->qn($data->sort_column_name) . ' ' . $data->sort_column_order);
$query->setLimit($length,$start);
OLD ANSWER
As of 08/Sept/14 The solutions from #Dasun or #escopecz arent working for me on J3.x
but this old trick is working for me which is nice,
$query->order($db->qn('id') . ' DESC LIMIT 25');
And About your specific requirement of wishing to fetch only 1 row you could use :
$rows = $db->loadObject();