I have database with 5 tables
students PK : ID -> anum, first, last
studentinfo PK/FK : ID -> why, student_commenets, finished, aidyear
Times PK/FK : ID -> signintime, counselor_start_time,
additional_time, finish_time
counselor PK/FK : ID -> firstcounselor, secondcounselor, thirdcounselor
Comments PK/FK : ID -> counselorcomments, additional_commenets
I have a page called signinpage.php
on that page I have to write to three different tables (student, studentinfo, and time)
My code is as fallows :
if (empty($errors) === true)
{
include('core/queries/inserts.updates.selects/students.php');
include('core/queries/inserts.updates.selects/studentinfo.php');
include('core/queries/inserts.updates.selects/signintime.php');
$dbh = null;
header('location: signedin.php');
exit();
}
each of the files are actual insert queries. (if you yall need to see them I will update this post)
The error I am having is :
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails (test.times,
CONSTRAINT times_ibfk_2 FOREIGN KEY (id) REFERENCES students
(id) ON DELETE CASCADE ON UPDATE CASCADE)
To add on to this, the first query (the students.php and the second query studentinfo.php)
are inserting just fine. Same ID, the problem occurs with the signintime inserting into table : times.
In phpmyadmin both tables (studentinfo and times) are configured alike with both have cascade on delete and update to the original table (student) since the student him/her starts the session (which is the PK ID).
How can I solved this error?
Edit :
<?php
require('core/init.php');
try
{
$null = NULL;
$query = $dbh->prepare("INSERT INTO `times` (signintime) VALUES (:signintime)");
$query->bindParam(':signintime' , $null);
$query->execute();
}
catch (PDOException $e)
{
error_log($e->getMessage());
die($e->getMessage());
}
?>
Your table design looks wrong to me. I'm assuming there can be multiple entries in the times table for each row in the students table. In that case, you would need the following columns in times:
id - PK
student_id - FK
signintime
counselor_start_time
additional_time
finish_time
Then each row for a particular student would have the same student_id value, but different id values.
The following statements and example is different from the tables you have mentioned but the thought is still the same.
The reason why the error was generated is because you are trying to insert a value on a child table in which that value is not yet present on the parent table. The child table means that it is dependent on the other table (which is the Parent).
To explain further, consider the following schema,
CREATE TABLE StudentList
(
ID INT PRIMARY KEY,
NAme VARCHAR(50)
);
CREATE TABLE AddressList
(
StudentID INT,
Address VARCHAR(50),
CONSTRAINT tb_fk FOREIGN KEY (StudentID)
REFERENCES StudentList(ID)
);
INSERT INTO StudentList VALUES (1, 'Jon');
INSERT INTO StudentList VALUES (2, 'Skeet');
INSERT INTO AddressList VALUES (1, 'Hello');
INSERT INTO AddressList VALUES (2, 'World');
INSERT INTO AddressList VALUES (1, 'Other Address');
There are two tables: StudentList and AddressList. The table Address is the child table and which is dependent to table StudentList (also called the Parent table). The only values that are allowed to be inserted on column StudentID of table AddressList is only 1 and 2 because those are the only IDs found on table StudentList.
When you try to insert record with ID other than 1 and 2 on table Address, eg
INSERT INTO AddressList VALUES (1, 'Other Address');
it will generate an error telling that:
Cannot add or update a child row: a foreign key constraint fails
(db_2_ec2e8.addresslist, CONSTRAINT tb_fk FOREIGN KEY
(StudentID) REFERENCES studentlist (ID)):
because the value of the column StudentID being inserted on the table is not available on the parent table (StudentList).
So, I hoped that this will help you understand now.
SQLFiddle Demo
Related
I am writing a query in PostgreSQL that I use in my php code where a user is supposed to be able to add actors to the list of actors by typing the actors name. I'm using a modifying CTE to do this because it needs to update three tables in the database:
Person(Person_ID:Serial, Name: Varchar,... other not relevant information, it's ok to leave null)
Personnel(Personnel_ID:Serial, Role: Varchar, Person_ID:Int (FK))
FilmPeople(Personnel_ID (FK), Media_ID (FK))
So the actor as a person is in the person table, then connected to a role in personnel, and the role is then connected to a media_ID.
The query so far:
WITH person_cte AS (
INSERT INTO Person(Name)
SELECT :actorname
WHERE NOT EXISTS (
SELECT 1 FROM person WHERE name = :actorname2)
RETURNING person_id
),
personnel_cte AS (
INSERT INTO Personnel(role, person_id)
SELECT 'Actor', person_id FROM person_cte
RETURNING personnel_id
)
INSERT INTO FilmPeople(Personnel_ID, Media_ID)
SELECT personnel_id, :id from personnel_cte¨
So the problem as you guys probably see is that my query so far only works if the actor doesnt exist in the database at all. It fails if it finds the actor in the Person table. What I actually want is if the Actor exists in person, then don't insert anything but do return the already existing person_id to the next cte. And then the same thing there, if the personnel (role) already exists for this actor, then move on with the personnel_id and only add the actor to the last table to connect him/her to a movie. And then even here, if it already exists then don't do anything.
EDIT: This is how the tables are created as of now:
CREATE TABLE Person(
Person_ID serial,
Name varchar(255),
DateOfBirth date,
Gender varchar(45),
CONSTRAINT PK_Person PRIMARY KEY (Person_ID)
);
CREATE TABLE Personnel(
Personnel_ID serial,
Role varchar(255),
Person_ID bigint,
CONSTRAINT PK_Personnel PRIMARY KEY (Personnel_ID),
CONSTRAINT FK_PersonPersonnel FOREIGN KEY (Person_ID)
REFERENCES Person(Person_ID)
);
CREATE TABLE FilmPeople(
Personnel_ID bigint,
Media_ID int,
CONSTRAINT PK_FilmPeople PRIMARY KEY (Personnel_ID, Media_ID),
CONSTRAINT FK_PersonnelFilmPeople FOREIGN KEY (Personnel_ID)
REFERENCES Personnel(Personnel_ID),
CONSTRAINT FK_MediaFilmPeople FOREIGN KEY (Media_ID)
REFERENCES Media(Media_ID)
);
When nothing is inserted, the returning clause comes back empty - so this is not the approach you want here. Instead, I would recommed joining the tables. For this to work properly, I would strongly suggest having unique keys on each table, like so:
person(name)
personnel(role,person_id)
filmpeople(personnel_id, media_id)
Then you can use on conflict:
with
person_cte as (
insert into person(name)
values (:actorname)
on conflict (name) do nothing
),
personnel_cte as (
insert into personnel(role, person_id)
select 'actor', p.person_id
from person p
where p.name = :actorname
on conflict (role, person_id) do nothing
)
insert into filmpeople(personnel_id, media_id)
select personnel_id, :id
from pl.personnel pl
inner person p on p.person_id = pl.person_id
where p.name = :actorname and pl.role = 'actor'
on conflict (personnel_id, media_id) do nothing
I'm creating an ADD/UPDATE/DELETE system for my database, and while coding the delete query I've found a constraint fails, preventing me from deleting certain data from a specific row.
Delete query:
if (isset($_GET['company'])) {
$id = $_GET['company'];
$query_del = " DELETE company.* , client.* , queries.*
FROM company
INNER JOIN client ON company.idcompany =
client.idcompany
INNER JOIN queries ON
client.idclient =
queries.idclient
WHERE company.idcompany = '" . $id . "'";
$result_del = mysqli_query($con, $query_del);
if ($result_del) {
header("location:companylist.php");
} else {
echo ' Erro: ' . mysqli_error($con);
}
}
Tables required:
company: idcompany , company_name
client: idclient , idcompany
queries: idclient
Error:
Cannot delete or update a parent row: a foreign key constraint fails
(db.client, CONSTRAINT client_ibfk_1 FOREIGN KEY (idcompany)
REFERENCES company (idcompany))
Basically, I'm getting the row number through URL and trying to delete all the data related with that idcompany on all three tables. Does somebody know how I can relate all three tables on a delete query?
To create the required table structure, I used these create statements:
CREATE TABLE company (
idcompany INT,
company_name VARCHAR(31),
PRIMARY KEY (idcompany));
CREATE TABLE clients (
idclient INT,
idcompany INT,
PRIMARY KEY (idclient),
FOREIGN KEY (idcompany) REFERENCES company(idcompany) ON DELETE CASCADE);
CREATE TABLE queries (
idclient INT,
FOREIGN KEY (idclient) REFERENCES clients(idclient) ON DELETE CASCADE);
Then, to delete all references to a company, you can simply run
DELETE FROM company WHERE idcompany = (insert company id variable here);
You can view a working sql demo here.
If you need to change the constrain to contain DELETE CASCADE then look at this post.
I am working on MySQL database. I am new to it that is why I am facing a problem. The problem is populating the child table with foreign key which is referencing to the parent table. I have two tables employee which contains following columns
id as a primary key,
first_name
last_name
birth_date
and a borrowed table which contains following columns
ref as a primary key
employId as a foreign key
book
The employeeId is referencing the primary key id of the employee table. So simply it means the one employee with same id can borrow multiple books. When I insert some data into the employee table It get inserted, but when I have to insert data into the borrowed table, I have to manually insert the value in employeeId column. Isn't it supposed to be populated automatically. or I am misunderstanding the concept of the foreign key.
My SQL Code
$uname = "root";
$pass = "";
$sname ="localhost";
$db ="nady";
//Making database connection
$con = mysqli_connect($sname,$uname,$pass,$db);
$t1 = "CREATE TABLE IF NOT EXISTS employee (
id smallint(5) unsigned AUTO_INCREMENT NOT NULL,
firstname varchar(30),
lastname varchar(30),
birthdate date,
PRIMARY KEY (id)
) ENGINE=InnoDB";
$con->query($t1);
$t2 = "CREATE TABLE IF NOT EXISTS borrowed (
ref int(10) unsigned NOT NULL auto_increment,
employeeid smallint(5) unsigned NOT NULL,
book varchar(50),
PRIMARY KEY (ref),
FOREIGN KEY (employeeid) REFERENCES employee(id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB";
$con->query($t2);
if(!$con->query($t2)){
echo $con->error;
}
$i1 = "INSERT INTO employee VALUES(NULL,\"Nadeem\",\"Ahmad\",22)";
$con->query($i1);
$i2 = "INSERT INTO borrowed VALUES(NULL,1,\"Ahmad\")";
$con->query($i2);
if(!$con->query($i2)){
echo $con->error;
}
Simple what I need is ; For example an employee with id 1. Who borrowed 3 books. So in the borrowed table the employeeId column will have three rows with values 1 and different books name. My point is how would I populate the employeeId column when I am inserting the data into it. Let say, John have have borrowed three books and have id 1 then how would I insert data to borrowed table with employeeId of john. I need the query for it. and also query to retrieve the books borrowed by john.
The foreign key is used to link two tables, indicating that the field in a column
(employId from borrowed, in your case) refers to the PRIMARY KEY of another table (id from employee).
When you're inserting a new line in borrowed, you have to indicate the user that is taking that book, to insert it in that line. You have to know the user that is doing it. If you have foreign key, you need the id of that user, which is supposed to be his unique identifier. To insert that John has taken a book, you need to know that John's id is 1.
If the user is already in your employee table and you know his first and last name, you can get the id with a simple select...
SELECT id FROM employee WHERE first_name='John' AND last_name='Smith'
... and then you can do the insert with the id obtained.
If it's new user, you need to add the user first to employee, then get the new id and then insert the new line in borrowed, to do this without having to re-query to employee table to get the new id, you can use the PHP mysqli::$insert_id/mysqli_insert_id function, that gives you the PRIMARY key of the last query. For example...
$con->query("INSERT INTO employee (first_name,last_name) VALUES ('Mark','Whatever')");
$newemployeeid = $con->insert_id;
$con->query("INSERT INTO borrowed (employeeid,book) VALUES (".$newemployeeid.",'Awesome Book Title')");
I hope it helps
Your just need change these lines
$employee_id = $con->insert_id;
$i2 = "INSERT INTO borrowed VALUES(NULL,".$employee_id.",\"Ahmad\")"
first you get last insert id as $employee_id through a inser_id mysql predefined function then you add this $employee_id in borrowed table inserted query.
You can also use the MySQL-function LAST_INSERT_ID(). This function fetches the id from any previous INSERT statement, in the OPs case after inserting a new employee into employee table.
So the INSERT statement can be shortened to this:
INSERT INTO borrowed (employeeid, book) VALUES(LAST_INSERT_ID(),'Ahmad')";
Also note, that it is not required (and probably not even allowed) to fill the column 'ref' since it has AUTO_INCREMENT.
Here's the link to MySQL's documentation/function reference about LAST_INSERT_ID().
I am creating a PHP website that use Apache web server (PHPmyAdmin)
I have 3 tables :
brand
brand_id (PRIMARY KEY) AUTO INCREMENT
brand_name
item
item_id (PRIMARY KEY) AUTO INCREMENT
item_category
model
model_id (PRIMARY KEY) AUTO INCREMENT
item_model
brand_id (FOREIGN KEY for brand.brand_id)
brand_name (FOREIGN KEY for item.item_id)
quantity
price
I have a problem when I want to insert new value into model table.
this is PHP Code that I use for inserting
if (isset($_POST['brand_id']));
$brand = ($_POST['brand_id']);
if (isset($_POST['item_id']));
$cat = ($_POST['item_id']);
if (isset($_POST['model']));
$model = ($_POST['model']);
if (isset($_POST['quantity']))
$quantity = ($_POST['quantity']);
if (isset($_POST['price']))
$price = ($_POST['price']);
$sql = "INSERT INTO model (item_model, brand_id, item_id, quantity, price)
VALUES ('$model', '$brand', '$cat', '$quantity', '$price')";
Note that I did not insert any value into the model_id because I think it will automatically increased for it is AUTO increment. I dont know whether I am right or wrong.
the isset values are passed from another PHP file. so this PHP basically just catch the thrown values from previous PHP file.
I had tried to insert value directly from the PHPmyAdmin using SQL statement and it yielded this error :
Cannot add or update a child row: a foreign key
constraint fails (`stock`.`model`, CONSTRAINT `fk_item_brand`
FOREIGN KEY (`brand_id`) REFERENCES `brand` (`brand_id`) ON UPDATE CASCADE)
and if I tried to put in a id value into one of the column, it will yield an error:
SQL query:
INSERT INTO `model`(`model_id`, `item_model`, `brand_id`, `item_id`, `quantity`, `price`)
VALUES (1,'a','1','1','a','a')
MySQL said: Documentation
#1062 - Duplicate entry '1' for key 'PRIMARY'
How do I insert a row into a table with foreign key inside PHP?
$sql = "INSERT INTO model (model_id,item_model, brand_id, item_id, quantity, price)
VALUES (null,'$model', '$brand', '$cat', '$quantity', '$price')";
Try this.
Add auto increment field and pass value null
I have two tables in my MySQL database, which were created like this:
CREATE TABLE table1 (
id int auto_increment,
name varchar(10),
primary key(id)
) engine=innodb
and
CREATE TABLE table2 (
id_fk int,
stuff varchar(30),
PRIMARY KEY (`id_fk`),
CONSTRAINT fk_id FOREIGN KEY(id_fk) REFERENCES table1(id) ON DELETE CASCADE
) engine=innodb
(These are not the original tables. The point is that table2 has a foreign key referencing the primary key in table 1)
Now in my code, I would like to add entries to both of the tables within one transaction. I'm doing this:
$table1 = new table1();
$table1->setTransaction($transaction);
$table1->name($name);
if (!$table->create()) {
foreach ($table1->getMessages() as $message) {
$this->flash->error($message);
}
$transaction->rollback("Can't save table1");
} else {
$table2 = new table2();
$table2->setTransaction($transaction);
$table2->setId($table1->getId());
$table2->setStuff($stuff);
if (!$table2->create()) {
foreach ($table2->getMessages() as $message) {
$this->flash->error($message);
}
$transaction->rollback("Can't save password");
}
$transaction->commit();
The table1 create() is successful, however, when I attempt the table2 create, it always errors out with a Constraint Violation stating that the Value of field "Id" does not exist on referenced table.How can I use phalcon transaction to save data into two referenced tables in a single transaction. Thanks.