I am having trouble with a major flaw with my database design. Below is my four tables:
Session Table:
SessionId SessionName
3 EROEW
Question Table:
QuestionId(PK) QuestionNo QuestionContent SessionId (FK)
11 1 Question1 3
12 2 Question2 3
13 3 Question3 3
Image_Question:
ImageQuestionId (PK) ImageId (FK) SessionId (Fk) QuestionNo (FK)
1 1 3 1
2 2 3 2
Image:
ImageId (PK) SessionId (Fk) QuestionNo (FK)
1 3 1
2 3 2
Now as you can see in the Image_Question Table, the QuestionNo refers to a QuestionNo which is non-unique or in other words a non unique field. Now I head this is bad practice.
Now I know you are going to say why not use QuestionId. Well the problem is that I can't use QuestionId because the images are uploaded to each question before a question is submitted and the only way we can give a question its own QuestionId is after the user has submitted the questions.
So what I tried to do was determine which question an uploaded image belongs to by getting the QuestionNo from the page as well as the SessionId.
Now as I have heard this is a bad way of doing it, I want to change QuestionNo (FK) in Image_Question to QuestionId (FK). But I am not going to be able to upload files and insert details of the uplaod after questions are submitted to get the QuestionId, to me that can't be done.
So my question is that is there a way we can some how store each uploaded image into a temp table, get the question number and sessionid for each image belongs to and then from there be able to find the QuestionId and store the QuestionId value in the Image_Question Table?
Below is my current php code where it inserts the values after image is uploaded:
Be very greatful if somebody can update code below but any answer will be helpful:
move_uploaded_file($_FILES["fileImage"]["tmp_name"],
"ImageFiles/" . $_FILES["fileImage"]["name"]);
$result = 1;
$imagesql = "INSERT INTO Image (ImageFile)
VALUES (?)";
//Dont pass data directly to bind_param store it in a variable
$insert->bind_param("s",$img);
//Assign the variable
$img = 'ImageFiles/'.$_FILES['fileImage']['name']; //GET THE IMAGE UPLOADED
$insert->execute();
$insert->close();
$lastImageID = $mysqli->insert_id;
$_SESSION['lastImageID'] = $lastImageID;
$_SESSION['ImageFile'] = $_FILES["fileImage"]["name"];
$sessid = $_SESSION['id'] . ($_SESSION['initial_count'] > 1 ? $_SESSION['sessionCount'] : ''); GET THE NAME OF THE SESSION
$sessionquery = "SELECT SessionId FROM Session WHERE (SessionName = ?)"; //FIND SESSIONID by finding it's SESSIONNAME
// Bind parameter for statement
$sessionstmt->bind_param("s", $sessid);
// Execute the statement
$sessionstmt->execute();
// This is what matters. With MySQLi you have to bind result fields to
// variables before calling fetch()
$sessionstmt->bind_result($sessionid);
// This populates $sessionid
$sessionstmt->fetch();
$sessionstmt->close();
$imagequestionsql = "INSERT INTO Image_Question (ImageId, SessionId, QuestionNo) //INSERT DETAILS INTO CURRENT IMAGE_QUESTION TABLE
VALUES (?, ?, ?)";
if (!$insertimagequestion = $mysqli->prepare($imagequestionsql)) {
// Handle errors with prepare operation here
echo "Prepare statement err imagequestion";
}
$qnum = (int)$_POST['numimage']; //QUESTION NUMBER IMAGE IS UPLOADED IN
$insertimagequestion->bind_param("iii",$lastImageID, $sessionid, $qnum);
$insertimagequestion->execute();
if ($insertimagequestion->errno) {
// Handle query error here
}
$insertimagequestion->close();
Your biggest problem is the fact that your schema isn't normalized. Doing so should help you some.
Here's how I recommend structuring your database:
Session:
SessionId SessionName
3 EROEW
Question:
QuestionId(PK) QuestionContent SessionId (FK)
11 Question1 3
12 Question2 3
13 Question3 3
Image:
ImageId (PK)
1
2
Image_Question:
ImageId (FK) QuestionId (FK) -- (Composite primary key)
1 11
2 12
The insert order for the tables should be:
Session -> Question -
\
-- Image_Question
/
Image -
You'll be dodging potential update issues, and data conflicts otherwise.
Related
I have a database that consists of 3 tables.
user: 4 columns userId [primary key], name, emailId, password
residentController: 3 columns userId [foreign], departmentId [foreign], checkDefault
checkDefault will be set to 1.
department with 6 columns: departmentId [primaryKey], departmentName, departmentDesc, departmentLink, checkDefault, departmentCategory
Here is the sequence that follows when a user registers for an android application. The following php script will be called.
It will add a record of the user into the database. After insertion of the data in the user table, I want to get all the "departmentNames" from department table and insert it into residentController. In the end, after particular user registers, then residentController must have these values populated into the residentController table.
userId departmentId checkDefault
---------------------------------
1 1 1
1 2 1
1 3 1
1 4 1
1 5 1
Here is my php script.
<?php
require "init.php";
$fullname = "Fahman Khan";//$_POST["user"];
$emailid = "fxk120#hotmail.com";//$_POST["user_name"];
$userpass = "Windows";//$_POST["user_pass"];
$sql_query = "insert into user values(NULL,'$fullname','$emailid','$userpass')";
if(mysqli_query($connection, $sql_query))
{
echo "<h2> Data insertion success</h2>";
//Get the user id of the the registered user
$sql_queryTwo = "SELECT userId FROM user WHERE emailId='".$emailid."'";
//Store the result of the query in a variable
$result= mysqli_query($connection,$sql_queryTwo);
$row = mysqli_fetch_array($result);
//Retrive the user id
$data = $row[0];
//Insert default departments into residentController
}
else
{
//echo "Data insertion error".mysqli_error($connection);
}
?>
My question is that in my current php script, I don't know how I can insert departmentID into residentController table. departmentId is a foreign key and in my current department table there are 5 departments. I just need help writing the part in my php where I can insert in values into my residentController table. As of now, the current php script only adds a new user, but I need help inserting values into my residentController table.
I'm trying to build a status/post. I have 4 fields in my table(post) id, user_id, status_time and status_content. I want to get the data on my status_content of 1 user_id only, can someone help me?
For example:
I have 3 users
user 1 = posted 3times
user 2 = posted 2times
user 3 = posted 5times
How can i only get all the data posted by user 3?
Sorry for my english.
Code to send data to my database
profile.php
if(isset($_POST['status_content'])){
$status_content = $_POST['status_content'];
if(!empty($_POST['status_content'])){
add_status($_SESSION['accts_id'], $status_time, $status_content);
}
}
core.php
function add_status($accts_id, $status_time, $status_content){
$sql = "INSERT INTO `post` (user_id, status_time, status_content) VALUES ('$accts_id', '$status_time', '$status_content')";
mysql_query($sql);}
you can use this as follows
to get data particularly for user 3 then
select status_content from post where user_id = '3'
to get data for any users
select status_content from post where user_id = $_SESSION['accts_id'];
[UPDATED]
I'm trying to insert form data into my sql table. The form data is a long questionnaire that has multiple questions. This means that the table I'm inserting into has multiple columns, 30 to be exact.
Is there a way for me to quickly insert one row of 30 columns with minimal or efficient code? Perhaps I can have the "name" value in my form be equal to the variable name in the my table? My form is a mixture of normal text fields and some checkbox groups.
I'm using php and hoping to use mysqli prepared statements.
TLDR: Can I shorten this ?:
$query = "INSERT INTO table (a, b, c, d, e , f , g , h ,i j, ........)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,....)";
mysqli_stmt_bind_param($stmt,'sssiiisiiiiiiiiiisss...', ....);
Or do I need to just brute force it?
You could try to call mysqli_stmt_bind_param using call_user_func_array and pass in an array of parameters:
$sql_link = mysqli_connect('localhost', 'my_user', 'my_password', 'world');
$type = "isssi";
$param = array("5", "File Description", "File Title", "Original Name", time());
$sql = "INSERT INTO file_detail (file_id, file_description, file_title, file_original_name, file_upload_date) VALUES (?, ?, ?, ?, ?)";
$sql_stmt = mysqli_prepare ($sql_link, $sql);
call_user_func_array('mysqli_stmt_bind_param', array_merge (array($sql_stmt, $type), $param);
mysqli_stmt_execute($sql_stmt);
source
Afaik no you can't shorten it.
But you could change your DB model that a result record only contains one answer which is linked to the question and to the user the answer is from. So you are also variable on how many questions there are in a quiz. And you don't have an oversize of 28 columns if the quiz only have 2 questions.
table: user
-----------
id (PK)
username
table: quiz
-----------
id (PK)
title (FK)
table: question
---------------
id (PK)
question
quiz_idfk (FK)
table: answer
-------------
id (PK)
answer
question_id (FK)
user_id (FK)
With that model the insert of a result would be (only pseudo code):
foreach($_POST['answer'] as $qid => $ans) {
// sql: INSERT INTO answer SET answer = :ans, question_id = :qid, user_id = :uid
// :ans the answer text ($ans)
// :qid the question id ($qid)
// :uid the currently logged in user
}
I want to delete a row from the database depending on what the file name of the image is. Lets say I have 2 tables below:
Image Table:
ImageId ImageFile
01 cat.png
02 dog.png
03 dog_2.png
Image_Question Table:
ImageId SessionId QuestionId
01 AAA 4
02 ABD 1
03 RTD 11
Lets say in my application I delete the file image dog_2.png, then I want it to delete the row which states dog_2.png in the Image Table (This is working fine) and be able to delete the row from the Image_Question Table where the row contains the same ImageId associated with the ImageId and ImageFile name from the Image Table (This is not working).
So for the above example the 2 tables should now look like this after deletion:
Image Table:
ImageId ImageFile
01 cat.png
02 dog.png
Image_Question Table:
ImageId SessionId QuestionId
01 AAA 4
02 ABD 1
But it does not delete the row from the Image_Question Table, how can I get this row to delete?
Below is the full code where it deletes the row from the Image Table and it contains most of the code which has been setup but not fully completed on deleting a row from the Image_Question Table:
$image_file_name = $_GET["imagefilename"];
$img = "ImageFiles/$image_file_name";
echo "$image_file_name was Deleted";
unlink("ImageFiles/$image_file_name");
$imagedeletesql = "DELETE FROM Image WHERE ImageFile = ?";
if (!$delete = $mysqli->prepare($imagedeletesql)) {
// Handle errors with prepare operation here
}
//Don't pass data directly to bind_param; store it in a variable
$delete->bind_param("s",$img);
$delete->execute();
if ($delete->errno) {
// Handle query error here
}
$delete->close();
$imagequestiondeletesql = "DELETE FROM Image_Question WHERE ImageId = ?";
if (!$deleteimagequestion = $mysqli->prepare($imagequestiondeletesql)) {
// Handle errors with prepare operation here
}
// Don't pass data directly to bind_param; store it in a variable
$deleteimagequestion->bind_param("s",....);
$deleteimagequestion->execute();
if ($deleteimagequestion->errno) {
// Handle query error here
}
$deleteimagequestion->close();
You can use a JOIN query to delete from multiple tables in a single query. I think this sort of statement will work for you:
$sql = "
DELETE img, img_q
FROM Image AS img
LEFT JOIN Image_Question AS img_q
ON img_q.ImageId = img.ImageId
WHERE img.ImageFile = ?";
I have a INSERT function where it inserts the image filename in the 'ImageFile' field in the "Image" table, each row has it's own ImageId thanks to auto number. An example of this is below:
ImageId ImageFile
23 orange.jpg
24 flowers.png
25 castle.png
26 orange.jpg
What I want to do is also insert the ImageId into another table with the QuestionId and SessionId so that this table (Image_Question) can use the ImageId to link the Image table with the Image Question table. But how do I code it so that when I insert image details in the table above, then it will retrieve it's ImageId and also store it in the ImageId in the Image_Question table. Example below:
ImageId SessionId QuestionId
23 AAA 1
24 AAA 2
25 AAA 3
26 AAA 4
I have coded the INSERT values for SessionId and QuestionId but just need help retrieving and inserting the ImageId. Below is the current code:
<?php
session_start();
//connect to db
$i = 0;
$insertimage = array();
for($i = 0; $i < $c; $i++ ){
$insertimage[] = "'". mysql_real_escape_string($_SESSION['id'] ) .
($_SESSION['initial_count'] > 1 ? $_SESSION['sessionCount'] : '') ."' ,'".
mysql_real_escape_string( $_POST['numQuestion'][$i] ) ."'";
}
$imagesql = "INSERT INTO Question (ImageId, SessionId, QuestionId)
VALUES (" . implode('), (', $insertimage) . ")";
echo($imagesql);
mysql_close();
?>
mysqli_insert_id() after query execute would do the trick
You can get the most recently generated auto_increment id using MySQL's last_insert_id() function. PHP exposes this through mysql_insert_id(). last_insert_id works on a per-connection basis so there is no need to worry about concurrent inserts crossing ids.