My Insert Into Statement is not working - java

I was working with UIs where the user will click the add button to add employees, but when I do it, it gives me an error like this
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`finalpayroll`.`personal_info`, CONSTRAINT `personal_info_ibfk_1`
How would I fix this?? I know I am using a parent key, and its foreign key is the User, and also take note that the parent key has already a data, but it seems my query won't work, why is that? I am using a foreign key with delete cascade and on update cascade so that when I delete a data, all of the child table rows will be deleted, vice versa. here's my key for adding or inserting statements
public void addEmployee(Personal p ,Contact c,Employee e) {
Connection conn = Jdbc.dbConn();
Statement statement = null;
String insert1 = "INSERT INTO personal_info (`First_Name`, `Middle_Initial`, `Last_Name`, `Date_Of_Birth`, `Marital_Status`, `Beneficiaries`) VALUES ('"+p.getFirstName()+"', '"+p.getMiddleInitial()+"'" +
" , '"+p.getLastName()+"', '"+p.getDateOfBirth()+"', '"+p.getMaritalStatus()+"', '"+p.getBeneficiaries()+"')";
try {
statement = conn.createStatement();
statement.executeUpdate(insert1);
statement.close();
conn.close();
JOptionPane.showMessageDialog(null, "Employee Added!!");
} catch(Exception ex) {
ex.printStackTrace();
}
}
Users table:
CREATE TABLE `users` (
`idusers` int(11) NOT NULL AUTO_INCREMENT,
`emp_id` varchar(45) DEFAULT NULL,
`emp_pass` varchar(45) DEFAULT NULL,
PRIMARY KEY (`idusers`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
Personal_info table:
CREATE TABLE `personal_info` (
`idpersonal_info` int(11) NOT NULL AUTO_INCREMENT,
`First_Name` varchar(45) DEFAULT NULL,
`Middle_Initial` varchar(45) DEFAULT NULL,
`Last_Name` varchar(45) DEFAULT NULL,
`Date_Of_Birth` varchar(45) DEFAULT NULL,
`Marital_Status` varchar(45) DEFAULT NULL,
`Beneficiaries` varchar(45) DEFAULT NULL,
PRIMARY KEY (`idpersonal_info`),
CONSTRAINT `personal_info_ibfk_1`
FOREIGN KEY (`idpersonal_info`)
REFERENCES `users` (`idusers`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1

You are trying to insert a record with 6 fields: First_Name, Middle_Initial, Last_Name, Date_Of_Birth, Marital_Status and Beneficiaries. Your schema is currently unknown but none of these fields seem to be a candidate foreign key to id of User table you mentioned. Thus I think there is a default value for that foreign key column and that default value is missing in User table.
Needless to say, you shouldn't have a default value for a foreign key of any table..
I am adding these information regarding your questions in comments and update on your question:
A foreign key is a link between a child table and parent table, personal_info and users tables in your case respectively. Child table's foreign key column must reference to a key value in parent table which means that for every value in child table's FK column, there must be a value in parent table's linked column.
Now, in your case when you try to insert a new personal_info record MySQL assigns a idpersonal_info to it, since you defined it as auto increment. But since there is a link to users table, MySQL searchs for the new idpersonal_info to be inserted in users table's idusers column. And as you are getting this exception, you surely don't have that value in the users table.
You can change your table structure as follows:
CREATE TABLE `personal_info` (
`idpersonal_info` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
... OTHER FIELD DEFINITIONS,
PRIMARY KEY (`idpersonal_info`),
CONSTRAINT `user_id_fk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`idusers`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB
And your query will need to include user_id field as well. So it will be something like this:
INSERT INTO personal_info
(`user_id`, `First_Name`, `Middle_Initial`, `Last_Name`, `Date_Of_Birth`, `Marital_Status`, `Beneficiaries`)
VALUES ( .... SET YOUR VALUES HERE. DON'T FORGET TO SET A VALID USER_ID

Looks like in your Personal_Info table you have a column called "finalpayroll", that points to a column in another table (a foreign key) and it's required (not nullable). In your insert you're not giving it a value. So what you could do is make that column nullable.
Or could be the other way around as #Konstantin Naryshkin is saying

What the error means is that you are trying to insert a value into a column with a foreign key a value that is not in the remote table.
I assume that there is a user column that we are not seeing. Since you are not explicitly setting the value, I assume that it is getting a default. The default value is not in the parent table.

Related

How to cascade delete grand children table entities if they have a reference to foreign key of parent and primary key of grand parent

I have table relation like this scenario -> event -> plan and they are:
scenario_table:
CREATE TABLE `scenario` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`plan_cycle_id` bigint(20) unsigned NOT NULL,
`created_by` varchar(255) DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `scenario_table_plan_cycle_id_fk` (`plan_cycle_id`),
CONSTRAINT `scenario_table_plan_cycle_id_fk` FOREIGN KEY (`plan_cycle_id`) REFERENCES `planning_cycle` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
event_table
CREATE TABLE `event` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`start_date` timestamp NULL DEFAULT NULL,
`end_date` timestamp NULL DEFAULT NULL,
`scenario_id` bigint(20) unsigned NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`created_by` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_scenario_id` (`scenario_id`),
CONSTRAINT `fk_scenario_id` FOREIGN KEY (`scenario_id`) REFERENCES `scenario` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
plan_table
CREATE TABLE `plan` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`scenario_id` bigint(20) unsigned NOT NULL,
`input` json DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`created_by` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `plan_scenario_id` (`scenario_id`),
CONSTRAINT `FKnjhfw18pms9j2yhtvu954hcsi` FOREIGN KEY (`scenario_id`) REFERENCES `scenario` (`id`), // this was not there in create table command but later added by mysql //
CONSTRAINT `plan_scenario_id` FOREIGN KEY (`scenario_id`) REFERENCES `event` (`scenario_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
Now I want to cascade delete scenario, event and plan for some particular scenario_id. When there are no grandchildren, scenario and event are getting deleter as expected. But when a new entry is present in plan which refers a scenario_id, am getting this error while deletion:
java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`db_dev`.`plan`, CONSTRAINT `plan_scenario_id` FOREIGN KEY (`scenario_id`) REFERENCES `event` (`scenario_id`))
I tried EAGER loading in eventEntity.java like this:
#OneToMany(fetch = FetchType.EAGER, mappedBy = "scenario", cascade = CascadeType.ALL)
private List<planEntity> planEntityList;
and in planEntity.java like this:
#ManyToOne
#JoinColumn(name = "scenario_id", referencedColumnName = "id")
private ScenarioEntity scenario;
How I can handle this case through *entity.java files ?
In MySql when a table is InnoDB you can Add Foreign Key Constraints. Foreign Key checks is done when you update or delete a record. The results of foreign Key checks depend on the design of your table as you may allow cascading the update or delete or prevent the process of update or delete.
The following is an example of a parent:
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
Example of child table that allows parent table to delete or update the (id) field of the parent table (Child also will be deleted):
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=INNODB;
Example of child table that prevents the update of (id) field of parent but allows parent table to be deleted. (Child also will be deleted):
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE
) ENGINE=INNODB;
Example of child table that prevents parent table to delete or update the (id) field of the parent table. This will give error like "Cannot Delete or Update a Parent Row: A Foreign Key Constraint Fails":
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
) ENGINE=INNODB;
You have four options when using foreign key constraints :
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT
RESTRICT : is the default if you don't include ON UPDATE/ON DELETE
CASCADE : Delete child when delete parent or update parent_id when id of parent changed.
for more information you can see FOREIGN KEY Constraints
There is also a variable that control foreign key checks. If you set it to 0 (false) you will disable foreign key checks.
SET FOREIGN_KEY_CHECKS=0;
Back to your database, I think it is better to modify your tables structure to allow cascade delete. You can also use ON DELETE SET NULL then later you can delete any record where parent_id=null. If you can't modify tables structure then you have to first delete records in child table before deleting parent record.

Transform composite primary key into ID [duplicate]

I have a pre-existing table, containing 'fname', 'lname', 'email', 'password' and 'ip'. But now I want an auto-increment column. However, when I enter:
ALTER TABLE users
ADD id int NOT NULL AUTO_INCREMENT
I get the following:
#1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key
Any advice?:)
Try this
ALTER TABLE `users` ADD `id` INT NOT NULL AUTO_INCREMENT;
for an existing primary key
If you don't care whether the auto-id is used as PRIMARY KEY, you can just do
ALTER TABLE `myTable` ADD COLUMN `id` INT AUTO_INCREMENT UNIQUE FIRST;
I just did this and it worked a treat.
If you want to add AUTO_INCREMENT in an existing table, need to run following SQL command:
ALTER TABLE users ADD id int NOT NULL AUTO_INCREMENT primary key
First you have to remove the primary key of the table
ALTER TABLE nametable DROP PRIMARY KEY
and now yo can add the autoincrement ...
ALTER TABLE nametable ADD id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
Well, you must first drop the auto_increment and primary key you have and then add yours, as follows:
-- drop auto_increment capability
alter table `users` modify column id INT NOT NULL;
-- in one line, drop primary key and rebuild one
alter table `users` drop primary key, add primary key(id);
-- re add the auto_increment capability, last value is remembered
alter table `users` modify column id INT NOT NULL AUTO_INCREMENT;
If you run the following command :
ALTER TABLE users ADD id int NOT NULL AUTO_INCREMENT PRIMARY KEY;
This will show you the error :
ERROR 1060 (42S21): Duplicate column name 'id'
This is because this command will try to add the new column named id to the existing table.
To modify the existing column you have to use the following command :
ALTER TABLE users MODIFY id int NOT NULL AUTO_INCREMENT PRIMARY KEY;
This should work for changing the existing column constraint....!
Delete the primary key of a table if it exists:
ALTER TABLE `tableName` DROP PRIMARY KEY;
Adding an auto-increment column to a table :
ALTER TABLE `tableName` ADD `Column_name` INT PRIMARY KEY AUTO_INCREMENT;
Modify the column which we want to consider as the primary key:
alter table `tableName` modify column `Column_name` INT NOT NULL AUTO_INCREMENT PRIMARY KEY;
Just change the ADD to MODIFY and it will works !
Replace
ALTER TABLE users ADD id int NOT NULL AUTO_INCREMENT
To
ALTER TABLE users MODIFY id int NOT NULL AUTO_INCREMENT;
Drop the primary index from the table:
ALTER TABLE `tableName` DROP INDEX `PRIMARY`;
Then add the id column (without a primary index). I have used a big int because I am going to have lots of data but INT(11) should work just as well:
ALTER TABLE `tableName` ADD COLUMN `id` BIGINT(11) NOT NULL FIRST;
Then modify the column with auto-increment (thanks php). It needs to be a primary key:
ALTER TABLE `tableName ` MODIFY COLUMN `id` BIGINT(11) UNSIGNED PRIMARY KEY AUTO_INCREMENT;
I have just tried this on a table of mine and it appears to have worked.
ALTER TABLE users CHANGE id int( 30 ) NOT NULL AUTO_INCREMENT
the integer parameter is based on my default sql setting
have a nice day
ALTER TABLE users ADD id int NOT NULL AUTO_INCREMENT primary key FIRST
For PostgreSQL you have to use SERIAL instead of auto_increment.
ALTER TABLE your_table_name ADD COLUMN id SERIAL NOT NULL PRIMARY KEY
ALTER TABLE `table` ADD `id` INT NOT NULL AUTO_INCREMENT unique
Try this. No need to drop your primary key.
This SQL request works for me :
ALTER TABLE users
CHANGE COLUMN `id` `id` INT(11) NOT NULL AUTO_INCREMENT ;
If you want to add an id with a primary key and identity:
ALTER TABLE user ADD id INT NOT NULL AUTO_INCREMENT FIRST , ADD PRIMARY KEY (id);
Check for already existing primary key with different column. If yes, drop the primary key using:
ALTER TABLE Table1
DROP CONSTRAINT PK_Table1_Col1
GO
and then write your query as it is.
Proceed like that :
Make a dump of your database first
Remove the primary key like that
ALTER TABLE yourtable DROP PRIMARY KEY
Add the new column like that
ALTER TABLE yourtable add column Id INT NOT NULL AUTO_INCREMENT FIRST, ADD primary KEY Id(Id)
The table will be looked and the AutoInc updated.

MYSQL update with inner join performance

The join is done on the primary key column of both these tables.
I have a doubt if I should fire a select query before the update or will this query be a good alternative?(in terms of performance)
order item table
order_item_id
order_id
quantity
unit_price
shipping_price
business_id
workflow_id
delivery_id
item_id
Orders table
billing_address_id
shipping_address_id
payment_mode
total_price
shipping_price
customer_id
order_id
Following is the query I fire from my Java service (using jdbc) :
UPDATE order_items t1
INNER
JOIN Orders t2
ON t2.order_id = t1.order_id
SET t1.workflow_id = ?
WHERE t1.order_item_id = ?
and t2.order_id = ?
and t2.customer_id = ?
and t1.delivery_id = ?
UPDATE : Adding show create table order_items
'CREATE TABLE `order_items` (
`order_item_id` int(20) NOT NULL AUTO_INCREMENT,
`quantity` int(10) unsigned NOT NULL,
`unit_price` int(10) unsigned NOT NULL,
`shipping_price` int(10) unsigned NOT NULL,
`pickup_date` datetime DEFAULT NULL,
`create_TS` datetime DEFAULT CURRENT_TIMESTAMP,
`update_TS` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`business_id` int(10) NOT NULL,
`order_id` int(11) NOT NULL,
`item_id` int(10) unsigned NOT NULL,
`delivery_id` int(11) NOT NULL,
`workflow_id` int(11) DEFAULT NULL,
PRIMARY KEY (`order_item_id`),
KEY `fk_business_id` (`business_id`),
KEY `fk_order_id` (`order_id`),
KEY `fk_item_id` (`item_id`),
KEY `fk_delivery_id` (`delivery_id`),
CONSTRAINT `fk_business_id` FOREIGN KEY (`business_id`) REFERENCES `business` (`MID`),
CONSTRAINT `fk_delivery_id` FOREIGN KEY (`delivery_id`) REFERENCES `delivery_mode` (`delivery_id`),
CONSTRAINT `fk_item_id` FOREIGN KEY (`item_id`) REFERENCES `item_business` (`item_id`),
CONSTRAINT `fk_order_id` FOREIGN KEY (`order_id`) REFERENCES `Orders` (`order_id`)
)
Talking in theory
You should have the minimum set of data before you do the join, so the join will actually be performed only on the data you need, and that is the case even with the update that is internally a special select and "write this data on the select"
Talking in practice
One of the job of any dbms is to perform an agressive level of optimization using database algebra and other stuff, so most of the time the time you spend in optimizing your query is actually futile because your dbms will perform the same level of optimization
So what
I would try to have the table the slimmest as possible but without getting too crazy, I performed on a aws db2.micro machine an update query on like 100k rows and it took it like 4 seconds, so in my opinion, try and see if you're getting the real result you need.
tl;dr just try and see if the speed increase

How to add an auto increment column in java?

I want to add the database from my jform and there's a column which will be auto incremented, like when i click done, the data will be inserted and a column receipt_no will have a value 1. Next time I click done then this value should be 2 and so on.
So the problem is, i have created a table with receipt_no as the primary key and auto increment, so what should be my query in java, to add the data correctly in the table.
String sql = "insert into table_name values('"++"',...)";
Can you help me in this query?
Step 1: Creating table in MySQL
CREATE TABLE `user_master` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`Firstname` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Step 2: Insert record
INSERT INTO user_master (`Firstname`) values('Vicky');
Step 3: Fetch record
SELECT * FROM user_master;
I can't comment so there is an answer to the comment you posted in your question:
If your table is
CREATE TABLE users(
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
firstname VARCHAR(25) NOT NULL,
lastname VARCHAR(25) NOT NULL,
);
You can simply auto_increment the primary by not giving it on your SQL request:
INSERT INTO users(firstname, lastname) VALUES('Steve', 'Jobs');
Java don't have to generate auto increment, it is SQL job :)

Problem with a Case of PKEY AND FKEY within the same table

I have a table which has a field ID as a primary key and another field PID as the Foreign Key to the ID Field. Both are of long DataTypes.
So this is my table struct
CREATE TABLE `myobj` (
`ID` BIGINT(100) NOT NULL AUTO_INCREMENT,
`FRIENDLY_NAME` VARCHAR(100) DEFAULT NULL,
`PARENT_ID` BIGINT(100) DEFAULT NULL,
`PARENT` VARCHAR(100) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `PARENT_ID` (`PARENT_ID`),
CONSTRAINT `myobj_ibfk_1` FOREIGN KEY (`PARENT_ID`) REFERENCES `myobj` (`ID`) ON DELETE CASCADE
) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
I use Hibernate as ORM to insert into the MySQL DB. The problem is
When One or more of the records which will be top level with no parent id, an error occurs with insert top-level records. It looks like in case of no parent id
it will accept only NULL.
But from Java Application code perspective, the datatype is long and hence when i insert an object through Hibernate, with default value as 0 ,it looks like a constraint violation
Cannot add or update a child row: a
foreign key constraint fails
(genericdb.myobj, CONSTRAINT
myobj_ibfk_1 FOREIGN KEY
(PARENT_ID) REFERENCES myobj
(ID) ON DELETE CASCADE)
This problem occurs also when setting 0 as the value thru sql CLI.
Second Secnario:
Also tried setting the Default Value for PARENT_ID as 0.
CREATE TABLE `myobj` (
`ID` BIGINT(100) NOT NULL AUTO_INCREMENT,
`FRIENDLY_NAME` VARCHAR(100) DEFAULT NULL,
`PARENT_ID` BIGINT(100) DEFAULT '0',
`PARENT` VARCHAR(100) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `PARENT_ID` (`PARENT_ID`),
CONSTRAINT `myobj_ibfk_1` FOREIGN KEY (`PARENT_ID`) REFERENCES `myobj` (`ID`) ON DELETE CASCADE
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
SO when i insert 0 into Parent_ID field, still error
Cannot add or update a child row: a
foreign key constraint fails
(genericdb.myobj, CONSTRAINT
myobj_ibfk_1 FOREIGN KEY
(PARENT_ID) REFERENCES myobj
(ID) ON DELETE CASCADE)
Kindly let me know if anything is wrong here.
The problem is that you're trying to point to row in myobj with the id 0, which doesn't exist. The default for that column should be null.
I'm quite sure that if you run select * from myobj where id = 0, you won't get any results back.

Categories