Kohana - Insert record with ignore duplicate - mysql

How to implement "insert ignore"? using kohana orm While adding multiple records, if few of them may already exist in database using below code adding of all 100 records will be declined.
$query = DB::insert('tablename', array('column1', 'column2','column3'));
foreach ($data as $d) {
$query->values($d);
}
try {
$result = $query->execute();
} catch ( Database_Exception $e ) {
echo $e->getMessage();
}
UPDATE:
Here is how i did This, i have to insert multiple records,
$Xtransactions = "INSERT IGNORE INTO `tablename` (`tid`, `tdate`, `appid`,
`userid`, `user_ip`) VALUES";
foreach ($objSas->trecord as $trow) {
$Xtransactions .= "(".$trow->tid.",'".
date('Y-m-d H:i:s', strtotime($trow->tdate))."',".
$trow->userid.",".
$trow->Xnumber.",'".
$trow->ip."'),";
}
$Xtransactions = substr($Xtransactions , 0, -1);
try {
DB::query(Database::INSERT, $Xtransactions )->execute();
} catch ( Database_Exception $e ) {
echo $e->getMessage();
}

With query builder this is impossible, try to write a raw query.
DB::query(Database::INSERT, 'INSERT IGNORE INTO table VALUES (...)')->execute();

I usually collect such modifications in static helper class, for example
<?php defined('SYSPATH') or die('No direct script access.');
class Helper_DB_Query{
/**
* #param Database_Query_Builder_Insert $insert query thant need to be converted
* #return Database_Query converted query
*/
public static function insert_to_insert_ignore( Database_Query_Builder_Insert $insert ){
$insert = (string) $insert;
$query = preg_replace("/^INSERT(.*)$/", "INSERT IGNORE $1", $insert);
return DB::query(Database::INSERT, $query);
}
}

Related

sql statement with where clause in function

I have written a function that will query the database. The sql statement includes a where clause. However, I keep getting this error
"Message: odbc_exec(): SQL error: [Microsoft][ODBC SQL Server
Driver][SQL Server]Invalid column name 'home'., SQL state S0022 in
SQLExecDirect".
The column name should be banner_category while "home_banner) is the value.
How should I go about achieving it?
public function get_landing_banners()
{
$query = $this->db->query(
'SELECT *
FROM o2o_banner
WHERE banner_category='home_banner'');
$data = array();
foreach ($query->result_array() as $row)
{
$data[] = $row;
}
return $data;
}
If you want to return an array try this:
public function get_landing_banners()
{
$this->db->select('*')->from('o2o_banner')->where('banner_category', 'home_banner');
$q = $this->db->get();
if ($q->num_rows() > 0) {
return $q->result_array();
}
}
Try this coding
public function get_landing_banners()
{
$query = $this->db->query(
'SELECT *
FROM o2o_banner
WHERE banner_category="home_banner"');
$data = array();
foreach ($query->result_array() as $row)
{
$data[] = $row;
}
return $data;
}

how to get recently affected rows attribute in model of codeigniter

primary key of title table is id and it is an auto-increment when I insert data to the table I need to return the id of currently inserted row.
my model function is,
function addDate($x, $y, $z) {
$sql = "INSERT INTO title (title,no,user) VALUES ('$x','$y','$z')";
$query = $this->db->query($sql );
if($this->db->affected_rows() > 0) {
return "ok";
} else {
return "err";
}
}
Please help me on this.
You are wrong. In your function you are getting these three parameters ($x, $y, $z) But in code you are Inserting ('$t','$n','$a')(Question is edited)
Use $this->db->insert_id() to get last insert id
Try this
function addDate($x, $y, $z) {
$data = array(
'title' => $x ,
'no' => $y ,
'user' => $z
);
if(!$this->db->insert('title', $data)){
return FALSE ;
}
else{
$lastId = $this->db->insert_id(); # add this
return $lastId;
}
}
FYI: Don't use $x, $y, $z. use meaningful names like $title, $no, $user
Codeigniter Active Record Class Version 2.2.0

Laravael4 db raw query using ON DUPLICATE KEY UPDATE drops error

I'm really fighting with a laravel ON DUPLICATE KEY UPDATE query I can't get it to work, so the query basically looks like
foreach ($queries as $query) {
$update_time = array('update_time' => date('Y-m-d H:i:s'));
$query = array_merge($update_time, $query);
$keysString = implode(", ", array_keys($query));
$indexes = "";
$values = "";
$updates = "";
foreach ($query as $i=>$v){
$values .= ':'.$v.',';
$updates .= $i.'="'.$v.'",';
}
//$holder = rtrim(str_repeat('?,', count($query)),',');
$updates = rtrim($updates,',');
DB::statement("INSERT INTO products ({$keysString}) VALUES ({rtrim($values,',')}) ON DUPLICATE KEY UPDATE {rtrim($updates,',')}")
}
but I get
SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters
How do I make a prepared statement in laravel4 for raw queries?
By default Laravel binds its data using ? and you are binding your data with :foo, meaning there is a mixture of the two approaches and PDO is getting sad about it.
PDO: Invalid parameter number: mixed named and positional parameters
Something like this should get you going in the right direction:
foreach ($queries as $query) {
// Add the update time without merging stuff
$query['update_time'] = date('Y-m-d H:i:s');
// How many bits of data do we have
$bindingCount = count($query);
// Same as before, just get the keys
$keyString = implode(", ", array_keys($query));
// Start off a bindings array with just the values
$bindings = array_values($query);
$updates = [];
foreach ($query as $field => $value){
$updates[] = "{$field} = ?";
$bindings[] = $value;
}
$valueString = implode(',', array_fill(0, $bindingCount, '?'));
$updateString = implode(',', $updates);
DB::statement("INSERT INTO products ({$keyString}) VALUES ({$valueString}) ON DUPLICATE KEY UPDATE {$updateString}", $bindings);
}

mysql_num_rows() expects parameter 1 to be resource, boolean in joomla component

When I execute the function below query execute successfully but I get a warning above the result the query:
mysql_num_rows() expects parameter 1 to be resource, boolean
How do I fix this?
public function retrieve()
{
$id=JRequest::getVar('id');
$db =JFactory::getDBO();
$sql="select *
from
#__npco_car,#__npco_namayeshgah,#__npco_agahi
where
#__npco_car.car_id='$id' and
#__npco_namayeshgah.id_namayeshgah=#__npco_agahi.id_namayeshgah and
#__npco_car.car_id=#__npco_agahi.car_id
";
$db->setQuery($sql);
$db->query();
$row = $db->getNumRows();
if($row == 1) {
return $db->loadAssocList();
} else {
$db = JFactory::getDBO();
$sql="select *
from
#__npco_car,#__npco_useragahi,#__npco_user
where
#__npco_car.car_id='$id' and
#__npco_user.id_user=#__npco_useragahi.id_user and
#__npco_car.car_id=#__npco_useragahi.car_id
";
$db->setQuery($sql);
return $db->loadAssocList();
}
}
Your code has several issues.
Never use unchecked/unvalidated request values, not even in examples!
Use the query builder.
Reduce coupling by a) setting the database in the constructor, which is done already in models, and b) retrieve the id in the controller.
You try to get all fields (*) from multiple tables, which have some column names in common. That will not work.
Have a look at JOINs.
This will work:
public function retrieve($id)
{
$query = $this->_db->getQuery(true);
$query->select('#__npco_car.*')->from(array('#__npco_car', '#__npco_namayeshgah', '#__npco_agahi'));
$query->where('#__npco_car.car_id = ' . (int) $id);
$query->where('#__npco_namayeshgah.id_namayeshgah = #__npco_agahi.id_namayeshgah');
$query->where('#__npco_car.car_id = #__npco_agahi.car_id');
$this->_db->setQuery($sql);
$rows = $this->_db->loadAssocList();
if (empty($rows))
{
$query = $this->_db->getQuery(true);
$query->select('#__npco_car.*')->from(array('#__npco_car, #__npco_useragahi, #__npco_user'));
$query->where('#__npco_car.car_id = ' . (int) $id);
$query->where('#__npco_user.id_user = #__npco_useragahi.id_user');
$query->where('#__npco_car.car_id = #__npco_useragahi.car_id');
$db->setQuery($sql);
$this->_db->setQuery($sql);
$rows = $this->_db->loadAssocList();
}
return $rows;
}
may be this is your issue..
Change your query as following
$sql="select *
from
#__npco_car,#__npco_namayeshgah,#__npco_agahi
where
#__npco_car.car_id='".$id."' and
#__npco_namayeshgah.id_namayeshgah=#__npco_agahi.id_namayeshgah and
#__npco_car.car_id=#__npco_agahi.car_id
";
$sql="select *
from
#__npco_car,#__npco_useragahi,#__npco_user
where
#__npco_car.car_id='".$id."' and
#__npco_user.id_user=#__npco_useragahi.id_user and
#__npco_car.car_id=#__npco_useragahi.car_id
";

MySql transqactions with dependent queries

I really hope you can help!
I use the following function to send a message in my PHP/MySql application:
public function sendMail($sender_id, $recipient_id, $subject, $message) {
$q = "INSERT INTO MAIL_MESSAGE (subject, message, date) VALUES ('$subject', '$message', NOW() )";
$s = mysql_query($q);
if (mysql_affected_rows()==1) {
$message_id = mysql_insert_id();
$q = "INSERT INTO MAIL (user_id, sender, message_id) VALUES ('$recipient_id','$sender_id','$message_id')";
$s = mysql_query($q);
if (mysql_affected_rows()==1)
return true;
}
return false;
}
I use two tables (MAIL_MESSAGE and MAIL) becuse the same '$sender_id' can send the same message to multiple '$recipient_id'.
Now the problem is that if the last query fails I have a row in MAIL_MESSAGE without the correspondent row in MAIL.
How can I solve this?
Transactions can help, but I don't know how to make it work!
Thanks in advance for your help.
Add "begin" at the start of the sequence to start a transaction. Commit the transaction only if both inserts succeed, otherwise rollback the transaction.
I do not know PHP, but based on your sample it would look something like the following:
public function sendMail($sender_id, $recipient_id, $subject, $message) {
$s = mysql_query("begin");
$q = "INSERT INTO MAIL_MESSAGE (subject, message, date) VALUES ('$subject', '$message', NOW() )";
$s = mysql_query($q);
if (mysql_affected_rows()==1) {
$message_id = mysql_insert_id();
$q = "INSERT INTO MAIL (user_id, sender, message_id) VALUES ('$recipient_id','$sender_id','$message_id')";
$s = mysql_query($q);
if (mysql_affected_rows()==1) {
$s = mysql_query("commit");
return true;
}
$s = mysql_query( "rollback" );
return false;
}