![](/img/trans.png)
[英]Insertion of values into a MySQL table referencing another table for a foreign key
[英]Insertion of data into mysql table containing foreign key gives an error
我的数据库中有两个表:
employee_details_table:
员工出席:
这是将数据插入employee_attendance的Java代码:
class Attendance
{
java.util.Date utilDate;
java.sql.Date sqlDate;
String attDate;
int empid;
String pa;
Connection con=null;
PreparedStatement statement=null;
ResultSet rs=null;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
try
{
empid=Integer.parseInt(jTextField1.getText());
sqlDate=new java.sql.Date(utilDate.getTime());
pa=jComboBox1.getSelectedItem().toString();
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null,e.getMessage());
}
String query = "Insert into employee_attendance (employee_id,attendance_for,present_or_absent) values (?,?,?)";
try
{
Class.forName("com.mysql.jdbc.Driver");
con=DriverManager.getConnection("jdbc:mysql:///hrmps?zeroDateTimeBehavior=convertToNull","root","root");
statement=con.prepareStatement(query);
statement.setInt(1,empid);
//sqlDate=new java.sql.Date(utilDate.getTime());
statement.setDate(2,sqlDate);
statement.setString(3, pa);
statement.executeUpdate();
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null,e.getMessage());
}
}
}
每当我尝试将数据插入employee_attendance时,都会出现以下异常:
“无法添加或更新子行:外键约束失败”
正如评论者已经说过的那样,错误告诉您问题所在。 “外键约束”冲突意味着您尝试使用不存在的父行的外键值将行插入子表中。
因此,您需要检查父表(Employee)中的数据以及尝试插入子表中的值(Attendance)。 您不匹配。
下面是一个完整的工作示例,创建一个数据库并插入行,所有行都塞到一个类中。 尽管这不是有价值的代码,但它是正确插入子行(三次)和不正确地插入子行(一次, demo
方法的最后一行)的有效demo
。
演示的要点是demo
方法中对insertAttendance
的四个调用。 我们为employee_
行标识符为1、2和3的行。因此,为这三个值中的任何一个插入attendance_
行都将成功。
this.insertAttendance ( conn , 2 …
this.insertAttendance ( conn , 1 …
this.insertAttendance ( conn , 3 …
当我们尝试一个无效的数字时,如果没有这样的employee_
,例如4
,那么我们将失败。 我们得到一个SQLException,它指出了违反外键 约束的情况 。 数据库正在执行引用完整性的工作 。 如果我们不阻止我们将创建一个“孤儿”行,一个attendance_
排不匹配employee_
行。
this.insertAttendance ( conn , 4 … // Throws SQLException for violation of the foreign key constraint.
本示例使用纯Java数据库H2数据库 。 您必须将其添加为依赖项才能运行此代码。 易于通过Maven等添加
运行时。
Tables established and populated.
Table dump: employee_
Employee id_: 1 | name_: Alfred
Employee id_: 2 | name_: Barbara
Employee id_: 3 | name_: Charlie
Table dump: attendance_
Attendance id_: 1 | fkey_employee_id_: 2 | when_expected_: 2016-01-23T10:00:00Z | status_: present
Attendance id_: 2 | fkey_employee_id_: 1 | when_expected_: 2016-01-23T10:00:00Z | status_: present
Attendance id_: 3 | fkey_employee_id_: 3 | when_expected_: 2016-01-23T10:00:00Z | status_: absent
SQLException: Referential integrity constraint violation: "CONSTRAINT_32: PUBLIC.ATTENDANCE_ FOREIGN KEY(FKEY_EMPLOYEE_ID_) REFERENCES PUBLIC.EMPLOYEE_(ID_) (4)"; SQL statement:
INSERT INTO attendance_ ( fkey_employee_id_ , when_expected_ , status_ ) VALUES ( ? , ? , ? ); [23506-191]
示例代码。
package com.example.h2example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant;
/**
* Demonstrates how to both properly and improperly insert rows into a child
* table.
*
* Caveat: Not production-worthy code. For demonstration purposes only. Use at
* your own risk.
*
* @author Basil Bourque
*/
public class App {
public static void main ( String[] args ) {
App app = new App ();
app.demo ();
}
private void demo () {
Connection conn = this.fetchConnection ();
this.insertAttendance ( conn , 2 , Instant.parse ( "2016-01-23T10:00:00Z" ) , "present" );
this.insertAttendance ( conn , 1 , Instant.parse ( "2016-01-23T10:00:00Z" ) , "present" );
this.insertAttendance ( conn , 3 , Instant.parse ( "2016-01-23T10:00:00Z" ) , "absent" );
this.dumpTable_Employee ( conn );
this.dumpTable_Attendance ( conn );
// Insert invalid value (BAD).
this.insertAttendance ( conn , 4 , Instant.parse ( "2016-01-23T10:00:00Z" ) , "absent" );
}
private Connection fetchConnection () {
Connection conn = null;
try {
Class.forName ( "org.h2.Driver" );
} catch ( ClassNotFoundException e ) {
// TODO: Handle exception.
System.out.println ( "Database failure: " + e );
return null;
}
// Specify a database named 'EmployeeAttendanceBogus.mv.db' in the Unix user’s home folder.
String dbFolderPath = "~/";
String dbName = "EmployeeAttendanceBogus";
String dbUrl = "jdbc:h2:" + dbFolderPath + dbName;
String dbUserName = "h2";
String dbPassword = "pw";
try {
// If database does not yet exist, it is automatically created.
conn = DriverManager.getConnection ( dbUrl , dbUserName , dbPassword );
} catch ( SQLException ex ) {
System.out.println ( "SQLException on DriverManager.getConnection: " + ex.getMessage () );
// TODO: Handle exception when no Connection is made.
}
if ( null == conn ) {
System.out.println ( "Database error. No Connection." );
// TODO: Handle exception when no Connection is made.
} else {
// ELSE got database connection. Normal.
this.recreateTables ( conn );
// this.dumpTable_Employee ( conn );
// this.dumpTable_Attendance ( conn );
}
return conn;
}
private void recreateTables ( Connection conn ) {
// Update database structure if needed.
StringBuilder sql = new StringBuilder ();
// Delete any existing tables.
sql.append ( "DROP TABLE IF EXISTS attendance_ ; " + " \n" ); // Drop child table first, because of referential integrity.
sql.append ( "DROP TABLE IF EXISTS employee_ ; " + " \n" );
// Define tables.
sql.append ( "CREATE TABLE employee_ " + " \n" );
sql.append ( "(" + " \n" );
sql.append ( "id_ IDENTITY PRIMARY KEY , " + " \n" ); // Primary key, Long type.
sql.append ( "name_ VARCHAR_IGNORECASE NOT NULL " + " \n" );
sql.append ( ")" + " \n" );
sql.append ( ";" + " \n" );
sql.append ( "" );
sql.append ( "CREATE TABLE attendance_ " + " \n" );
sql.append ( "(" + " \n" );
sql.append ( "id_ IDENTITY PRIMARY KEY , " + " \n" ); // Primary key, Long type.
sql.append ( "fkey_employee_id_ BIGINT , " + " \n" );
sql.append ( "when_expected_ TIMESTAMP NOT NULL , " + " \n" );
sql.append ( "status_ VARCHAR_IGNORECASE NOT NULL " + " \n" ); // Domain: "present" | "absent" .
sql.append ( ")" + " \n" );
sql.append ( ";" + " \n" );
sql.append ( "" );
sql.append ( "ALTER TABLE attendance_ ADD FOREIGN KEY ( fkey_employee_id_ ) REFERENCES employee_( id_ ) ;" );
sql.append ( "" );
sql.append ( "INSERT INTO employee_ ( name_ ) VALUES ( 'Alfred' ) ;" );
sql.append ( "INSERT INTO employee_ ( name_ ) VALUES ( 'Barbara' ) ;" );
sql.append ( "INSERT INTO employee_ ( name_ ) VALUES ( 'Charlie' ) ;" );
System.out.println ( "Tables established and populated.\n" );
try ( Statement stmt = conn.createStatement () ) {
stmt.executeUpdate ( sql.toString () );
} catch ( SQLException ex ) {
System.err.println ( "SQLException: " + ex.getMessage () );
// TODO: Handle exception.
}
}
private void dumpTable_Employee ( Connection conn ) {
StringBuilder sql = new StringBuilder ();
sql.append ( "SELECT * FROM employee_ ;" );
try ( PreparedStatement pstmt = conn.prepareStatement ( sql.toString () ) ) {
try ( ResultSet rs = pstmt.executeQuery (); ) {
System.out.println ( "Table dump: employee_" );
while ( rs.next () ) {
long id = rs.getLong ( "id_" );
String name = rs.getString ( "name_" );
System.out.println ( "Employee id_: " + id + " | name_: " + name );
}
System.out.println ( "" );
}
} catch ( SQLException ex ) {
System.err.println ( "SQLException: " + ex.getMessage () );
// TODO: Handle exception.
}
}
private void dumpTable_Attendance ( Connection conn ) {
StringBuilder sql = new StringBuilder ();
sql.append ( "SELECT * FROM attendance_ ;" );
try ( PreparedStatement pstmt = conn.prepareStatement ( sql.toString () ) ) {
try ( ResultSet rs = pstmt.executeQuery (); ) {
System.out.println ( "Table dump: attendance_" );
while ( rs.next () ) {
long id = rs.getLong ( "id_" );
long fkey = rs.getLong ( "fkey_employee_id_" );
java.sql.Timestamp whenExpectedTs = rs.getTimestamp ( "when_expected_" );
Instant whenExpected = whenExpectedTs.toInstant (); // Convert as soon as possible from java.sql.Timestamp to java.time.
String status = rs.getString ( "status_" );
System.out.println ( "Attendance id_: " + id + " | fkey_employee_id_: " + fkey + " | when_expected_: " + whenExpected + " | status_: " + status );
}
System.out.println ( "" );
}
} catch ( SQLException ex ) {
System.err.println ( "SQLException: " + ex.getMessage () );
// TODO: Handle exception.
}
}
private void insertAttendance ( Connection conn , long employeeId , Instant whenExpected , String status ) {
StringBuilder sql = new StringBuilder ();
sql.append ( "INSERT INTO attendance_ ( fkey_employee_id_ , when_expected_ , status_ ) VALUES ( ? , ? , ? );" );
try ( PreparedStatement pstmt = conn.prepareStatement ( sql.toString () ) ) {
pstmt.setLong ( 1 , employeeId );
pstmt.setTimestamp ( 2 , java.sql.Timestamp.from ( whenExpected ) );
pstmt.setString ( 3 , status );
int rowsAffected = pstmt.executeUpdate ();
} catch ( SQLException ex ) {
System.err.println ( "SQLException: " + ex.getMessage () );
// TODO: Handle exception.
}
}
}
顺便说说…
您的代码表明您可能对java.util.Date
和java.sql.Date
感到困惑。 第一个是日期和时间,而第二个则仅是没有日期的日期。
避免使用旧的java.util.Date类(和.Calendar),因为它的设计不良,令人困惑且麻烦。 改用Java 8和更高版本内置的java.time。
java.sql类型也一样。 但是我们必须继续使用它们,直到我们的JDBC驱动程序更新为直接使用java.time类型。 在此之前,请尽可能简短地使用java.sql类型将数据移入/移出数据库。 接收到值后立即从java.sql转换为java.time。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.