What is wrong with this Code Igniter mySQL query? - mysql

I have two tables for storing information about a user. One is for authentication, the other is information the user will enter themselves. I am writing a model that will be used when the user interacts with this information. The following method is to return data for display and modification.
I need a query that will return 'email' and 'username' from $accounts_table and * from $profiles_table. I can't seem to get my head around the JOIN syntax though. I understand how joins work, but my queries throw sentax errors.
function get_userdata($id){
$data = array();
$this->db->get_where($this->profiles_table, array('user_id' => $id));
$this->db->join($this->accounts_table.'.email', $this->accounts_table.'.id = '.$this->profiles_table.'.user_id');
$data= $this->db->get();
return $data;
}

I see a couple of issues:
You should be using $this->db->where(), instead of $this->db->get_where(). get_where() executes the query immediately.
$this->db->get_where('user_id', $id);
Also the first argument of $this->db->join() should only be the table name, excluding the field.
$this->db->join($this->accounts_table, $this->accounts_table.'.id = '.$this->profiles_table.'.user_id');
And you're returning $data which is just an empty array(). You would need to pass the query results to $data like this:
$data = $record->result_array();

get_where executes the query. So, your join is its own query, which doesn't work.
You need to break get_where into where and from.
Also, in MySQL, you JOIN a table, not a field. If you want that field, add it to the SELECT.
$this->db->select($this->profiles_table.'.*');
$this->db->select($this->accounts_table.'.email,'.$this->accounts_table.'.username');
$this->db->from($this->profiles_table);
$this->db->where('user_id', $id);
$this->db->join($this->accounts_table, $this->accounts_table.'.id = '.$this->profiles_table.'.user_id');
$data = $this->db->get();
NOTE: $this->db->get() returns a query object, you need to use result or row to get the data.

I think you've a mistake:
$this->db->join($this->accounts_table.'.email', $this->accounts_table.'.id = '.$this->profiles_table.'.user_id');
First parameter should a table NOT a field: $this->accounts_table.'.email' is wrong IMHO. Or only a typo :)

Related

Laravel Select Query Accessing Returned Data

I've been working with Laravel for a short time, and am confused about accessing data retrieved from queries. I'm trying to save data to variable but am getting the following:
Trying to get property of non-object
Queries tried:
$data = DB::table('table_1')->select('user_id', 'email')->where('email', '=', Input::get('email_address'))->get();
// also tried
$data = DB::table('table_1')->where('email', '=', Input::get('email_address'))->pluck('user_id');
// accessing data
$userID = $data->user_id;
Both return the same.
To elaborate a little bit, ->get() will return a Collection. You might iterate over it as an array, but you can profit from methods that this class offers. pluck is one of these.
That's why $userID = $data->user_id; wouldn't work.
first() did the trick, rather than get().
$data = DB::table('table_1')->select('user_id', 'email')->where('email', '=', Input::get('email_address'))->first();

Zend Framework - join query

I build a function
public function getBannedByLogin($commentId)
{
$sql = $this->getDbAdapter()->select()
->from(array('comments' => 'comments'), array())
->join(array('users' => 'qengine_users'),
'comments.bannedBy = users.userId',
array())
->where('commentId = ?', $commentId)
;
$row = $this->fetchRow($sql);
return $row['login'];
}
And there are problems, that does'nt work! :D
Let's I explain you. Column 'bannedBy' from comments returns id of user, who give a ban. I need to join this with table users to load a login field. Where i have mistakes?
I assume the code works in the sense of not throwing an exception. If so, your code is OK, you just specifically tell Zend_Db not to select any columns.
public function getBannedByLogin($commentId)
{
$sql = $this->getDbAdapter()->select()
->from(array('comments' => 'comments'))
->join(array('users' => 'qengine_users'),
'comments.bannedBy = users.userId')
->where('commentId = ?', $commentId)
;
$row = $this->fetchRow($sql);
return $row['login'];
}
The last argument to from() and join() functions is an array of columns you wish to select. If you pass in an empty array, no columns are selected. No argument = select everything. You can, of course, specify only the columns you need too.

Import of 50K+ Records in MySQL Gives General error: 1390 Prepared statement contains too many placeholders

Has anyone ever come across this error: General error: 1390 Prepared statement contains too many placeholders
I just did an import via SequelPro of over 50,000 records and now when I go to view these records in my view (Laravel 4) I get General error: 1390 Prepared statement contains too many placeholders.
The below index() method in my AdminNotesController.php file is what is generating the query and rendering the view.
public function index()
{
$created_at_value = Input::get('created_at_value');
$note_types_value = Input::get('note_types_value');
$contact_names_value = Input::get('contact_names_value');
$user_names_value = Input::get('user_names_value');
$account_managers_value = Input::get('account_managers_value');
if (is_null($created_at_value)) $created_at_value = DB::table('notes')->lists('created_at');
if (is_null($note_types_value)) $note_types_value = DB::table('note_types')->lists('type');
if (is_null($contact_names_value)) $contact_names_value = DB::table('contacts')->select(DB::raw('CONCAT(first_name," ",last_name) as cname'))->lists('cname');
if (is_null($user_names_value)) $user_names_value = DB::table('users')->select(DB::raw('CONCAT(first_name," ",last_name) as uname'))->lists('uname');
// In the view, there is a dropdown box, that allows the user to select the amount of records to show per page. Retrieve that value or set a default.
$perPage = Input::get('perPage', 10);
// This code retrieves the order from the session that has been selected by the user by clicking on a table column title. The value is placed in the session via the getOrder() method and is used later in the Eloquent query and joins.
$order = Session::get('account.order', 'company_name.asc');
$order = explode('.', $order);
$notes_query = Note::leftJoin('note_types', 'note_types.id', '=', 'notes.note_type_id')
->leftJoin('users', 'users.id', '=', 'notes.user_id')
->leftJoin('contacts', 'contacts.id', '=', 'notes.contact_id')
->orderBy($order[0], $order[1])
->select(array('notes.*', DB::raw('notes.id as nid')));
if (!empty($created_at_value)) $notes_query = $notes_query->whereIn('notes.created_at', $created_at_value);
$notes = $notes_query->whereIn('note_types.type', $note_types_value)
->whereIn(DB::raw('CONCAT(contacts.first_name," ",contacts.last_name)'), $contact_names_value)
->whereIn(DB::raw('CONCAT(users.first_name," ",users.last_name)'), $user_names_value)
->paginate($perPage)->appends(array('created_at_value' => Input::get('created_at_value'), 'note_types_value' => Input::get('note_types_value'), 'contact_names_value' => Input::get('contact_names_value'), 'user_names_value' => Input::get('user_names_value')));
$notes_trash = Note::onlyTrashed()
->leftJoin('note_types', 'note_types.id', '=', 'notes.note_type_id')
->leftJoin('users', 'users.id', '=', 'notes.user_id')
->leftJoin('contacts', 'contacts.id', '=', 'notes.contact_id')
->orderBy($order[0], $order[1])
->select(array('notes.*', DB::raw('notes.id as nid')))
->get();
$this->layout->content = View::make('admin.notes.index', array(
'notes' => $notes,
'created_at' => DB::table('notes')->lists('created_at', 'created_at'),
'note_types' => DB::table('note_types')->lists('type', 'type'),
'contacts' => DB::table('contacts')->select(DB::raw('CONCAT(first_name," ",last_name) as cname'))->lists('cname', 'cname'),
'accounts' => Account::lists('company_name', 'company_name'),
'users' => DB::table('users')->select(DB::raw('CONCAT(first_name," ",last_name) as uname'))->lists('uname', 'uname'),
'notes_trash' => $notes_trash,
'perPage' => $perPage
));
}
Any advice would be appreciated. Thanks.
Solved this issue by using array_chunk function.
Here is the solution below:
foreach (array_chunk($data,1000) as $t)
{
DB::table('table_name')->insert($t);
}
There is limit 65,535 (2^16-1) place holders in MariaDB 5.5 which is supposed to have identical behaviour as MySQL 5.5.
Not sure if relevant, I tested it on PHP 5.5.12 using MySQLi / MySQLND.
This error only happens when both of the following conditions are met:
You are using the MySQL Native Driver (mysqlnd) and not the MySQL client library (libmysqlclient)
You are not emulating prepares.
If you change either one of these factors, this error will not occur. However keep in mind that doing both of these is recommended either for performance or security issues, so I would not recommend this solution for anything but more of a one-time or temporary problem you are having. To prevent this error from occurring, the fix is as simple as:
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
While I think #The Disintegrator is correct about the placeholders being limited. I would not run 1 query per record.
I have a query that worked fine until I added one more column and now I have 72k placeholders and I get this error. However, that 72k is made up of 9000 rows with 8 columns. Running this query 1 record at a time would take days. (I'm trying to import AdWords data into a DB and it would literally take more than 24 hours to import a days worth of data if I did it 1 record at a time. I tried that first.)
What I would recommend is something of a hack. First either dynamically determine the max number of placeholders you want to allow - i.e. 60k to be safe. Use this number to determine, based on the number of columns, how many complete records you can import/return at once. Create the full array of data for you query. Use a array_chunk and a foreach loop to grab everything you want in the minimum number of queries. Like this:
$maxRecords = 1000;
$sql = 'SELECT * FROM ...';
$qMarks = array_fill(0, $maxInsert, '(?, ...)');
$tmp = $sql . $implode(', ', $qMarks);
foreach (array_chunk($data, $maxRecords) AS $junk=>$dataArray) {
if (count($dataArray) < $maxRecords)) { break; }
// Do your PDO stuff here using $tmp as you SQL statement with all those placeholders - the ?s
}
// Now insert all the leftovers with basically the same code as above except accounting for
// the fact that you have fewer than $maxRecords now.
Using Laravel model, copy all 11000 records from sqlite database to mysql database in few seconds. Chunk data array to 500 records:
public function handle(): void
{
$smodel = new Src_model();
$smodel->setTable($this->argument('fromtable'));
$smodel->setConnection('default'); // sqlite database
$src = $smodel::all()->toArray();
$dmodel = new Dst_model();
$dmodel->setTable($this->argument('totable'));
$dmodel->timestamps = false;
$stack = $dmodel->getFields();
$fields = array_shift($stack);
$condb = DB::connection('mysql');
$condb->beginTransaction();
$dmodel::query()->truncate();
$dmodel->fillable($stack);
$srcarr=array_chunk($src,500);
$isOK=true;
foreach($srcarr as $item) {
if (!$dmodel->query()->insert($item)) $isOK=false;
}
if ($isOK) {
$this->notify("Przenieśliśmy tabelę z tabeli : {$this->argument('fromtable')} do tabeli: {$this->argument('totable')}", 'Będzie świeża jak nigdy!');
$condb->commit();
}
else $condb->rollBack();
}
You can do it with array_chunk function, like this:
foreach(array_chunk($data, 1000) as $key => $smallerArray) {
foreach ($smallerArray as $index => $value) {
$temp[$index] = $value
}
DB::table('table_name')->insert(temp);
}
My Fix for above issue:
On my side when i got this error I fixed it by reducing the the bulk insertion chunk size from 1000 to 800 and it worked for me.
Actually there were too many fields in my table and most them contains the details descriptions of size like a complete page text. when i go for there bulk insertion the service caused crashed and through the above error.
I think the number of placeholders is limited to 65536 per query (at least in older mysql versions).
I really can't discern what this piece of code is generating. But if it's a gigantic query, There's your problem.
You should generate one query per record to import and put those into a transaction.

Codeigniter mysql where not equal to query

Mysql codeigniter query is not working properly.
Suppose if mysql table looks like this:
user_id|user_name
1|john
2|alex
3|sam
Here user_name is unique
The following query should return false if user_name=john and user_id=1 and true if say user_name=john and user_id=2.
$this->db->get_where('user', array('user_name' => $name,'user_id !=' => $userid));
But it returns true in the case user_name=john and user_id=1.
Can anyone suggest me an alternative way of querying not equal to.
print($this->db->last_query()) gives:
SELECT * FROM (user) WHERE user_name = 'john' AND user_id != '1'
Why dont you use simple $this->db->query('your query');
Simply try this, Add the desired condition in the where function.
$this -> db -> where('invitee_phone !=', $user_phone);
You can go follwoing way too. It work for me
$total = 5;
$CI = get_instance();
$CI->load->database();
$CI->db->order_by('id','asc');
$topusers = $CI->db->get_where('users',array('user_type != 1 && `status` =' => 1),$total,0);
echo $CI ->db ->last_query();
die;
and if still not work for you can go with #rohit suggest: $this->db->query('your query');
Type 1:
Using ->where("column_name !=",$columnname) is fine for one column.
But if you want to check multi columns, you have to form an array inside where clause.
Like this
$whereArray = array(
"employee_name" => $name,
"employee_id !=" => $id,
);
$this->db->select('*')->from('employee')->where($whereArray);
Type 2:
We can just write exactly what we want inside where.
Like
$thi->db->where(("employee_id =1 AND employee name != 'Gopi') OR designation_name='leader#gopis clan'");
Type 2 is good for working with combining queries, i mean paranthesis "()"
you can follow this code:
$query = $this->db->select('*')->from('employee')->where('user_name', $name)->where('user_id !=', $userid)->get();
$last_query = $this->db->last_query();
$result = $query->result_array();
if you pass $name = 'john' and $userid = '1' then it return empty array.
The problem with using $this->db->query('your query'); is that it is not portable. One of the most important reasons to embrace the query builder methods is so that no matter what database driver you use, CodeIgniter ensures that the syntax is appropriate.
If a bit of discussion was possible, I'd probably like to hear why you need composite primary identifiers in your table and I'd like to see what your table schema looks like. However, I think the time for discussion has long passed.
Effectively, you want to return a boolean result stating the availability of the combination of the username AND the id -- if one is matched, but not both, then true (available).
To achieve this, you will want to search the table for an exact matching row with both qualifying conditions, count the rows, convert that integer to a boolean, then return the opposite value (the syntax is simpler than the explanation).
Consider this clean, direct, and portable one-liner.
return !$this->db->where(['user_name' => $name,'user_id' => $userid])->count_all_results('user');
this will return false if the count is > 0 and true if the count is 0.

"No result was found for query although at least one row was expected." Query should display records though in Symfony

I'm trying to retrieve content using two items in the URL. Here is the php/symfony code that should do it:
$em = $this->getDoctrine()->getEntityManager();
$repository = $this->getDoctrine()
->getRepository('ShoutMainBundle:Content');
$query = $repository->createQueryBuilder('p')
->where('p.slug > :slug')
->andWhere('p.subtocontentid > :parent')
->setParameters(array(
'slug' => $slug,
'parent' => $page
))
->getQuery();
$content = $query->getSingleResult();
However, when this code is executed it returns the following error:
No result was found for query although at least one row was expected.
I have done some tests, and the data held in the $slug and $page variables hold the correct information. I have also tested the MySQL query and the query brings up the desired result, which confuses me further.
Have I missed something?
As it was answered here
You are getting this error because you are using the
getSingleResult() method. it generates an Exception if it can't find
even a single result. you can use the getOneOrNullResult() instead
to get a NULL if there isn't any result from the query.
Query#getSingleResult(): Retrieves a single object. If the result
contains more than one object, an NonUniqueResultException is thrown.
If the result contains no objects, an NoResultException is thrown. The
pure/mixed distinction does not apply.
No result was found for query although at least one row was expected.
Another reason could be:
You did this
$query = $this->getEntityManager()
->createQuery('
SELECT u FROM MyBundle:User u
WHERE u.email = :email')
->setParameter('email', $email);
return $query->getSingleResult();
Instead of this
$query = $this->getEntityManager()
->createQuery('
SELECT u FROM MyBundle:User u
WHERE u.email = :email')
->setParameter('email', $email);
$query->setMaxResults(1);
return $query->getResult();
Don't you want to use "=" instead of ">" ?
If you've got this message because used
$content = $query->getSingleResult();
you can just replace it with the row below
$content = $query->getOneOrNullResult(AbstractQuery::HYDRATE_SINGLE_SCALAR) ?? 0;