Select MySQL table with dynamic content - php

I have a bunch of tables that are like Client# and the # changes. Is there a way to create a query to query that table based on the client number you get from logging in as their use?
Example to give idea:
$q2 = "SELECT * FROM users WHERE username = '".$_SESSION['username']."'";
$result2 = mysql_query($q2,$conn);
$row = mysql_fetch_assoc($result2);
$_CLIENT_ID = $row['CLIENTID'];
$q2 = "SELECT * FROM client+".$_CLIENT_ID."";
Is there a better way to do this?
I'm trying to keep clients in their own tables so they do not get to massive.

I'm trying to keep clients in their own tables so they do not get to massive.
This is almost always the wrong strategy. The table size isn't as important as how you have indexed it for access, and it can be partitioned later, should that become necessary. The proper way to handle this is simply a column in one table which identifies the client id.
With a proper client-identifying column you can query as:
SELECT othertable.*
FROM
users
JOIN othertable ON users.CLIENTID = othertable.CLIENTID
WHERE users.username = '$_SESSION['username']'
Dealing with dynamic table names becomes troublesome not only because it is more difficult to query against. You cannot, for example, use a placeholder in place of a table name with many parameterized query APIs like PDO & MySQLi:
// Won't work with a PDO prepared statement. :clienttable place holder isn't allowed
SELECT * FROM :clienttable WHERE value=:someval

Related

Delete from all tables where ip equals that ip

I have a lot of tables in my SQL database, and I want to delete from all tables from it where the IP matches a certain IP in one statement/Query. Is there a way to do it quickly?
Something like:
DELETE FROM * tables where ip = '$ip';
Is there a way to do this?
Like this
$tables = ['table1','table2','table3'];
foreach($tables as $table){
//DELETE FROM `$table` tables where ip = :ip;
}
Just make absolutely certain you are using prepared statements, and "canned" table names. Never concatenate user input into your sql.
Imagine this $ip = "1' OR 1=1"; Now all your data has been deleted. AKA sql Injection.
Because your innocent query:
DELETE FROM table where ip = '$ip'
Becomes:
DELETE FROM table where ip = '1' OR 1=1
AND 1 is always equal to 1
If you can't see the data your putting in when you look at the query, use prepared statements. Because, you never know when you will re-purpose a piece of code and if it's not done right from the get go, your setting yourself up for a lot of headaches.
This may be a one time thing you are doing, but if you plan to leave the code around, I would still use prepared statements.
Can't you just separate them by a semicolon?
DELETE FROM table1 WHERE id = 1;
DELETE FROM table2 WHERE id = 1;
DELETE FROM table3 WHERE id = 1;
Looking into the details of the question that you have provided. You can do this with the help of Dynamic SQL.
Step 1) With the help of information_schema, prepare the dynamic SQL to delete the record from the table. You will get dynamic SQL like below
Delete from table1 where ColumnName = 'IPAddress';
Delete from table2 where ColumnName = 'IPAddress';
Step 2) With the help of Execute Statement. Run that dynamic SQL and this will delete all the records from those tables where the record has IP address in that column.

MySQL Select Logic

So I'm working on an assignment right now and I can't wrap my head around the logic.
I have to populate an HTML select box with a list of courses based on a qualification code where the user is not already enrolled in a course.
Here is my current code:
//Get logged in users id
$currentID = getIDForUser($_SESSION['username']);
//Get logged in users qualification code
$qualificationCode = getUserQualification($currentID);
//Get and display list of avaliable courses for qualificationCode
$query = mysql_query("");
while($row = mysql_fetch_array($query)) {
$courseName = $row['courseName'];
$courseCode = $row['courseCode'];
print("<option value='$courseCode'>$courseName</option>");
}
The layout of the database is as follows
Courses table:
Courseoccurrence table:
So, basically at this stage the combo box will populate with Multimedia & Design as well as Data Structures & Algorithms. However, if I select Multimedia and enroll in it, it will not populate the box with that course anymore.
Stop using mysql_*, it's deprecated. Go with mysqli_* or PDO instead.
Not absolutely necessary, but you might want to change your collation from latin1_swedish_ci to utf8_general_ci or you will face problems if you ever decide to put special characters in your DB.
Now, to actually address your question:
In your question you don't say what your problem is, specifically, but based on the title I assume that you know how to build everything except for the SELECT query.
So, first you want to select all the courses that the current user is enrolled in. Then, based on the result, you want to fetch all courses that are not in the list you just selected.
This can be done fairly easily with a subselect:
// Assuming $mysqli is an OOP database handle
$query = $mysqli->prepare('SELECT `courseName`, `courseCode` FROM `Courses` WHERE `courseCode` NOT IN (SELECT `courseCode` FROM `Courseoccurrence` WHERE `personID` = ?)');
$query->bind_param('i', $currentID);
$result = $query->get_result();
while($row = $result->fetch_array())
// ...
SQL Explanation:
I think SELECT, FROM, WHERE and NOT require no explanation.
IN checks whether a value is in a list like 'A' IN ('A', 'B', 'C').
And (SELECT ...) is a so-called subselect (see Subqueries), which is a simple SELECT whose result you can use in your query, and in case of it having only one column (because we only select courseCode), it can be used as an argument to IN.

PDO Create Temp Table and Select

I am trying to create a temporary table from the results of multiple tables that are alike (same table structure). After creating the temporary table and runing the subsequent queries, I would like to store the results from the temporary table in an array to be accessible later in the script/program. I have tried searching for an answer and can't seem to find one.
I have tried nextRowset() as well as separating the queries, but nothing seems to be working like I expect it to work.
Here is my code:
$pdo = new PDO("mysql:host=".$_SESSION['server'].";dbname=data".$_SESSION['sysident'],$user,$pass);
$stmt = $pdo->prepare("DROP TABLE IF EXISTS $tabletocreate;
CREATE TEMPORARY TABLE $tabletocreate LIKE table1;
INSERT INTO $tabletocreate (SELECT * FROM table1 WHERE (MISC LIKE '%:memno%' OR MEMNO = :memno)) UNION (SELECT * FROM table2 WHERE (MISC LIKE '%:memno%' OR MEMNO = :memno)) UNION (SELECT * FROM table3 WHERE (MISC LIKE '%:memno%' OR MEMNO = :memno)) ORDER BY SLIPNO;
SELECT * FROM $tabletocreate");
$stmt->bindParam(":memno",$_SESSION['memno']);
$stmt->execute();
$stmt->nextRowset();
$test = $stmt->fetchAll();
print_r($test);
I am unsure as to why the results are not being stored into the array. From what I can tell, everything seems right and no errors occur when the script is ran. I appreciate any help that anyone can offer.
UPDATE - I found out why the query wasn't working. I was using a "-" in the table name I was trying to create which isn't allowed.
You cannot run multiple queries in a single ->query() call. This is a security measure in the underlying PHP mysql drivers, to prevent some form of SQL injection attacks. Doesn't matter which DB interface library you're using, because they all use the same underlying drivers. You'll have to run each seperate query separately:
->query("DROP TABLE IF EXISTS ...");
->query("CREATE TEMPORARY TABLE ...");
->query("INSERT INTO ...");
etc...
I was trying to create a table name with a "-" in the table name. After removing this from the table name, all the queries executed successfully and my PHP code worked as intended.

How do I search multiple mySQL tables to find one specific row?

I have three tables: adapters, connectors, components
I need to be able to search them all to find a corresponding Part Number (part_num)
The part number is unique so I don't have to worry about multiple entries.
I use GET to find the part number in the URL, set it to $num, and then do the SELECT
What I've found is that I should use UNION, however the three tables have different columns and it gives me an error when trying to do the select. In the example below
Using UNION to find references from other tables
This is my code:
if(isset($_GET['num'])) {
$num = $_GET['num'];
$result = mysql_query("SELECT * FROM connectors WHERE part_num = '$num' UNION SELECT * FROM adapters WHERE part_num = '$num' UNION SELECT * FROM components WHERE part_num = '$num'"); }
Any help would be appreciated, so thanks in advance SO =)
You should probably have a fourth table Parts that identifies to which type table each part_num has been allocated. However, without that, you could still get what you're after with outer joins (wasteful though):
SELECT * FROM
connectors
LEFT JOIN adapters USING(part_num)
LEFT JOIN components USING(part_num)
WHERE
part_num = ?
Note that I have used ? as you really should be using prepared statements: if you don't know why, or what they are, read about Bobby Tables.
How about taking not all columns, but only titles or so on?
$sSql = "SELECT id, title, 1 FROM connectors WHERE part_num = '$num'
UNION
SELECT id, title, 2 FROM adapters WHERE part_num = '$num'
UNION
SELECT id, title, 3 FROM components WHERE part_num = '$num'";
You must adopt it to your table fields, but with this logic you will have an array where by the Third column (in my example), you can know if it is connector, adapter or component found, then generate proper links or do other actions with this data.
Another Way is to make Multi query, which will return multiple results by one database request. There are some ways to use it - using mysqli (http://lt.php.net/manual/en/mysqli.multi-query.php) or some of Adodb or PDO libraries.
Hope it will help.
To use UNION, the 3 recordsets must have the same number of columns, so you'll have to specifed which columns from each table that you want. From there, you'll have a single results set with the data from each of the 3 queries.

Best practice to execute multiple SQL queries using PHP PDO

What is the best practice to execute multiple SQL queries using PHP PDO?
I have 4 tables and each of them is running on MyISAM. As such they do not have Foreign Key support. It's a one-to-many design whereby there is 1 main table and the other table contains reference to the main table in the form of IDs.
For now, what I do is that I run the first query to get the ID from the main table. Once that is executed, I then perform another query to query other tables using the ID from the first query. Results from both the queries are then merged together (array_merge) and then displayed to the user.
Here's my code so far. I think you will get the gist and you can most probably tell that I'm a super beginner in PHP. :)
$sql1 = "SELECT * FROM student_records WHERE name=? LIMIT 1";
$stmt1 = $db->prepare($sql1);
$stmt1->execute(array($name));
$e11 = $stmt1->fetch();
$id = $e1['id'];
$sql2 = "SELECT file_name FROM images WHERE id=? LIMIT 1";
$stmt2 = $db->prepare($sql2);
$stmt2->execute(array($id));
$e2 = $stmt2->fetch();
$e = array_merge($e1, $e2);
I think that the code above is somewhat repetitive and redundant. Is there any suggestion and tips on how I can improve this?
Use joins, and don't use SELECT * (select only the columns you need):
SELECT file_name
FROM student_records AS sr
JOIN images AS i ON sr.id = i.id
WHERE sr.name=?

Categories