select from mysql db with 300 tables using a default prefix - php

I have a program that selects from about 200 tables with prefix. eg PBN_products, PBN_address, PBN_others.
Instead of appending the prefix on each table for the select statement, is there a way of defining the prefix as default value and do the selection?
$prefix=GET['prefix'];
mysql_connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD);
mysql_select_db(DB_DATABASE);
$sql = 'SELECT price, description, title, cost'.
'FROM products, address, others';
How can I define the prefix not to include in all tables? I have 200 tables.

I would look into a class to do some simple query abstraction or some kind of ORM lib that does this. A sample would be like this.
class Query {
function from($tbl){
return new Table($tbl);
}
}
class Table {
var $prefix = 'PBN_';
var $tblname = '';
function Table($name){
$this->tblname = $this->prefix.$name;
}
function select($cols, $where = false, $order = false, $limit = false){
$query = "SELECT {$cols} FROM {$this->tblname}";
if($where) $query .= " WHERE ".$where; //add where
if($order) $query .= " ORDER BY ".$order; //add order
if($limit) $query .= " LIMIT ".$limit; //add limit
return $query;
}
}
$q = new Query;
$results = mysql_query($q->from('products')->select('*'));
This is obviously nowhere near complete or secure. Just a sample of how an abstraction class could speed up your sql and do you your prefixes for you.

You could define an array with the table names, and loop through that array. When you append the array item to the string, put "PBN_" hardcoded in front of that name.
$arr = array("products","address","others");
$sql = "SELECT price, description, title, cost FROM ";
foreach ($arr as $tablename) {
$sql = $sql . "PBN_" . $tablename . ", ";
}
$sql = substr($sql, 0, -2); // Remove last comma
You can then add all the tablenames to the array, and the prefix will automatically be added.

How about something like this?
$prefix = GET['prefix'];
// add prefix to table names
foreach (array("products", "address", "others") as &$table)
{
$table = $prefix.$table;
}
mysql_connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD);
mysql_select_db(DB_DATABASE);
$sql = 'SELECT price, description, title, cost'.
'FROM '.$table[0].', '.$table[1].', '.$table[2];

You could do something like this?
$prefix = '';
if(isset($_GET['prefix'])){
$prefix = mysql_real_escape_string(stripslashes($_GET['prefix']));
}
$sql = "SELECT price, description, title, cost
FROM {$prefix}products, {$prefix}address, {$prefix}others";
EDIT: I agree on the comments that this is bad practice... An alternative would be to store the prefixes in another table and pass an ID of that table in the GET. This would make you less vulnarable to SQL injections.
$prefix = "";
if(isset($_GET['prefixid'])){
$prefixid = mysql_real_escape_string(stripslashes($_GET['prefixid']));
$query = "SELECT prefix FROM prefixes WHERE prefixid = $prefixid";
$result = mysql_query($query);
$prefix = mysql_result($result, 0, 0);
}
$sql = "SELECT price, description, title, cost
FROM {$prefix}products, {$prefix}address, {$prefix}others";

Related

PHP/SQL - Combining AND & OR in a foreach()

I'm sending json to the server like this:
{"data":{"tags":[{"tag":"Paris"},{"tag":"New York"},{"tag":"London"}]},"terms":{"term":"index"}}
... and with foreach() I'm appending the provided tags to the query:
$query = "SELECT name FROM accounts
WHERE name = '".$term."'";
foreach($tags as $t=>$tag){
$tag = $tag['tag'];
$query.=" AND city = '".$tag."'";
}
... to replicate this:
SELECT name FROM accounts
WHERE name=$term
AND city=$tag
AND city=$tag
AND city=$tag;
But how should the foreach() look like if I want to provide replicate this:
SELECT name FROM accounts
WHERE name=$term
AND (city=$tag OR city=$tag OR city=$tag);
It's better way to use IN clause in query and implode function to form it:
$tags_list = array();
foreach($tags as $t=>$tag){
$tags_list[] = $tag['tag'];
}
$query = "SELECT name FROM accounts
WHERE name = '".$term."'";
if ($tags_list) {
$query .= " AND city IN ('".implode("', '", $tags_list)."')";
}
The Problem with this is that in your sql query the column name couldn't have 2 tags at the same time. for example
WHERE name = true AND name = false
wouldn't make any sense.
so u should use something like this
WHERE name in ($tag, $term, $tag2);
and therefore u should adapt your php code as well
$first = true;
$query = "SELECT name FROM accounts
WHERE name2 = '$term' and name in ("
foreach($tags as $t=>$tag){
$tag = $tag['tag'];
if($first == false) {
$query.=",";
}
$query.="'".$tag."'";
$first = false;
}
$query.=")";

Create MySQL query with IDs from results

I have a a form which let's the user select what they want to display. Now the results of this looks like that: 9, 10, 11. These are IDs from the table.
These are the IDs of the type they what to show. I have my query already, but I want to add this part at the end of my query.
So in this case:
$query = "type_ID = $result1 or type_ID = $result2 or type_ID = $result3"
if printed out with echo:
type_ID = 9 or type_ID = 10 or type_ID = 11
How can I achieve this?
I tried to loop and it,however this did not work and I am confused how to do add the MySQL code to this.
$result = $result . $_GET['type_ID'][$i]
I'm a tad unsure of what it is you are trying to achieve but from what I understand this should do it:
<?php
$tID = $_GET['type_ID'];
$query = 'SELECT * FROM table WHERE';
$i = 0;
foreach($tID AS $id){
if($i == 0){
$query .= ' type_ID = ' . $id;
$i++;
}else{
$query .= ' OR type_ID = ' . $id;
}
}
Although if you are only looking for the type_ID I'd still recommend using IN() like so:
<?php
$tID = $_GET['type_ID'];
$query = "SELECT * FROM table WHERE type_ID IN (" . implode(',',$tID) . ")";
In works just like OR, just instead of having to write multiple OR you can just use a single IN() :)
Have you try this ?
$sql = "SELECT * FROM table WHERE ".$query;

passing array of values in sql select statement of where condition

$sql = "select id from table_name ";
$result = mysql_query($sql);
$data = array();
while($row = mysql_fetch_assoc($result))
{
$data[] = $row[id];
}
/* $data contains id's fetched from sql query from db.now i want to pass this id's(array of values) in $data array one by one to below select query in where condition and obtain desired result for each id.My question is how to pass an array of values to the below select statement I dont know how to do this.Any help is greatly appreciated.*/
$query = "select * from table where id1 = $data[] ";
$query = "select * from table where `id1` in (" . implode(', ', $data) . ")";
You should use the cross database function in Moodle called get_in_or_equal()
list($where, $params) = $DB->get_in_or_equal($data, SQL_PARAMS_NAMED);
$sql = "SELECT *
FROM {table}
WHERE $id {$where}"
$records = $DB->get_records_sql($sql, $params);
You can use the IN clause.
When you are totally sure you only have numeric values in your $data array. You can do the following:
$query = "select * from table where id1 IN(" . implode(',', $data) . ")";
You can use this:
$comma_separated = implode(",", $data);
if ($comma_separated != "")
$query = "select * from table where id1 IN($comma_separated)";

Problems with using PDO to perform an advanced search query

I have the following code and all of the search functions work except for the title field. So I can search by genre, date, location etc... but not by title. When attempting to search by title nothing is returned at all. Can anyone help me with this?
Also, is there a more efficient way to count all the fields before limiting it for use in pagination later on?
$today = date("Y-m-d");
$query = "SELECT * FROM TABLE_NAME WHERE Date >= '$today'";
$bind = Array();
if ($_GET["Title"] && $_GET["Title"] != "") {
$query .= " and Title like %?%";
$bind['Title'] = $_GET['Title'];
}
if ($_GET["Genre"] && $_GET["Genre"] != "") {
$query .= " and Genre like %?%";
$bind['Genre'] = $_GET['Genre'];
}
if ($_GET["Location"] && $_GET["Location"] != "") {
$query .= " and Location like %?%";
$bind['Location'] = $_GET['Location'];
}
if ($_GET["Date"] && $_GET["Date"] != "") {
$query .= " and Date = %?%";
$bind['Date'] = $_GET['Date'];
}
$stmt = $db->prepare($query);
$stmt->execute($bind);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$num = count($rows);
$query .= " ORDER BY Date LIMIT $limit, 9";
$stmt = $db->prepare($query);
$stmt->execute($bind);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Edit: After everyone's help I thought I would post my now revised code for future reference. It turns out the other fields were not working, but instead due to the if statement all this was nested in the code simply wasn't being executed.
$today = date("Y-m-d");
$query = "SELECT * FROM TABLE_NAME WHERE Date >= '$today'";
$countq = "SELECT count(*) FROM TABLE_NAME WHERE Date >= '$today'";
$bind = Array();
if ($_GET["Title"] && $_GET["Title"] != "") {
$query .= " and Title like :title";
$countq .= " and Title like :title";
$bind[':title'] = "%{$_GET['Title']}%";
}
if ($_GET["Genre"] && $_GET["Genre"] != "") {
$query .= " and Genre like :genre";
$countq .= " and Genre like :genre";
$bind[':genre'] = "%{$_GET['Genre']}%";
}
if ($_GET["Location"] && $_GET["Location"] != "") {
$query .= " and Location like :loc";
$countq .= " and Location like :loc";
$bind[':loc'] = "%{$_GET['Location']}%";
}
if ($_GET["Date"] && $_GET["Date"] != "") {
$query .= " and Date = :date";
$countq .= " and Date = :date";
$bind[':date'] = "{$_GET['Date']}";
}
$stmt = $db->prepare($countq);
$stmt->execute($bind);
$rows = $stmt->fetchAll();
$num = count($rows);
$query .= " ORDER BY Date LIMIT $limit, 9";
$stmt = $db->prepare($query);
$stmt->execute($bind);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
all of the search functions work
With the given query it is not true
From PDO tag wiki:
placeholders cannot represent an arbitrary part of the query, but a complete data literal only. Neither part of literal, nor whatever complex expression or a syntax keyword can be substituted with prepared statement.
Prepare FULL literal first: $name = "%$name%"; and then bind it.
As for the "more" efficient method for pagination - yes, oh yes.
With your current way of counting data you don't actually need other queries. as you have ALL the data already and can paginate it as well.
But of course it will pollute all the memory soon. So, if you want to get a count of rows from database, get the very count: run the same query but instead of SELECT * make it "SELECT count(*)
There are not any errors returned, that's why I am so confused
From PDO tag wiki again:
It is essential to set ERRMODE_EXCEPTION as a connection option as it will let PDO throw exceptions on connection errors. And this mode is the only reliable way to handle PDO errors.

How to query a database with an array? WHERE = 'array()'

I'm wondering how to query a database using an array, like so:
$query = mysql_query("SELECT * FROM status_updates WHERE member_id = '$friends['member_id']'");
$friends is an array which contains the member's ID. I am trying to query the database and show all results where member_id is equal to one of the member's ID in the $friends array.
Is there a way to do something like WHERE = $friends[member_id] or would I have to convert the array into a string and build the query like so:
$query = "";
foreach($friends as $friend){
$query .= 'OR member_id = '.$friend[id.' ';
}
$query = mysql_query("SELECT * FROM status_updates WHERE member_id = '1' $query");
Any help would be greatly appreciated, thanks!
You want IN.
SELECT * FROM status_updates WHERE member_id IN ('1', '2', '3');
So the code changes to:
$query = mysql_query("SELECT * FROM status_updates WHERE member_id IN ('" . implode("','", $friends) . "')");
Depending on where the data in the friends array comes from you many want to pass each value through mysql_real_escape_string() to make sure there are no SQL injections.
Use the SQL IN operator like so:
// Prepare comma separated list of ids (you could use implode for a simpler array)
$instr = '';
foreach($friends as $friend){
$instr .= $friend['member_id'].',';
}
$instr = rtrim($instr, ','); // remove trailing comma
// Use the comma separated list in the query using the IN () operator
$query = mysql_query("SELECT * FROM status_updates WHERE member_id IN ($instr)");
$query = "SELECT * FROM status_updates WHERE ";
for($i = 0 ; $i < sizeof($friends); $i++){
$query .= "member_id = '".$friends[$i]."' OR ";
}
substr($query, -3);
$result = mysql_query($query);

Categories