UCanAccessSQLException: constraint violation - java

I'm having problems with my Java program.
I'm using MS Access as a database and UCanAccess to connect to the database.
When I'm trying to insert a text into the database, I get an Exception:
net.ucanaccess.jdbc.UcanaccessSQLException: integrity constraint violation: unique constraint or index violation; ENTRIES_PRIMARYKEY table: ENTRIES
This is the SQL statement, that results in the exception:
"INSERT INTO Entries (Text, Title, Date, Time) VALUES"
+ "(\"" + text + "\", \"" + title + "\", \"" + date + "\", \"" + time + "\");";
The primary keys of table Entries is (Title, Date).
The information I'm inserting does not exist in the table.
I've made a System.out.println() containing the same string to make sure the variables contain the correct information, and they do.
Can someone tell me what I'm doing wrong?

(from comment to question:)
I tried inserting a row, and it worked. But when I tried to insert more rows, the problem occurred.
If the Primary Key for the table is (Title, Date) then the values in those two columns (fields) must be unique across all rows. That is, you can insert a row that looks like
Text Title Date Time
---------- ------ ---------- --------
some text Title1 2015-06-01 05:56:15
but if you try to insert another row like this
Text Title Date Time
---------- ------ ---------- --------
other text Title1 2015-06-01 06:15:44
the insert will fail because that combination of Title and Date already exists in the table. Yes, that row "doesn't exist" because the Text and Time values are different, but the Primary Key constraint doesn't care; it only looks at the Title and Date columns.
If you really need to insert that second row then you'll need to change the Primary Key for the table.

Related

Getting the next autonumber value specific to a connection (concurrency)

I have a data entry page that displays a generated case number as:
This number is the next available autonumber for the primary key of the table. It was retrieved using:
String sql="SELECT AUTO_INCREMENT \r\n"
+ "FROM information_schema.tables \r\n"
+ "WHERE table_name = 'dataentrytbl' \r\n"
+ "AND table_schema = DATABASE();";
stmt=conn.prepareStatement(sql);
rs=stmt.executeQuery(sql);
if(rs.next()) reply=rs.getInt("AUTO_INCREMENT");
Everything works perfect. The system is online, multiple users are using the data entry page and getting concurrency problems. The reason is all of them are getting the same generated auto id so when they click the ENTER button, an error is thrown.
Question: is there a way to generate a unique value for the autonumber primary key together with the connection? So if there are 5 users accessing the page simultaneously, is there a way to generate 5 different values for each of them?

Writing data to tables with relationship in SQL Server

I have two different tables with multiple columns. Like the following
Table1
ID CUSTOMER PRODUCT DETAILS
21 joe phone
22 doe shoe
23 john cup
Table2
PRODUCT ID COST ID
1 9000 21
2 600 22
3 30 23
ID in table1 is primary index and PRODUCT ID in table2 is the primary index. The common link between these two tables is ID. I used the following query to read the values.
String query = "SELECT * FROM Table1 c1 INNER JOIN Table2 c2 ON c1.ID = c2.ID";
But my problem is when I am adding new row, I use the following queries for it.
String query1 = "INSERT INTO Table1(CUSTOMER) VALUES ('" + alex + "') ";
String query2 = "INSERT INTO Table2(COST) VALUES ('" + 500 + "') ";
Since ID is not the primary index for Table2, I get a NULL value in ID. When I try to read again, since ID are not matched the I cannot reload the saved data.
Edit
This is what I have tried based on the explanation given here,
String foreignKey = "ALTER TABLE Table2 ADD FOREIGN KEY (ID) REFERENCES Table1(ID)";
Still the column ID is null in table2. Do I need combine the queries in some sort to acheive the result ? Because I just execute queries one by one as follows.
Statement stmt = connect.createStatement();
stmt.executeUpdate(query1);
stmt.executeUpdate(query2);
stmt.executeUpdate(foreignKey);
General idea here - you need to get autogenerated id from first "insert" to Table1 and set "ID" at Table2 explicitly with this id in the second "insert". You can see how to do that here for example.
Foreign key in your second table - is just a constraint, that helps to prevent data's inconsistency. Its main purpose - is to give some message to you when you're trying to put some data with foreign key that doesn't exist in primary table. Also it can help (if you set this while creating foreign key) to remove from Table2 rows linked on foreign key with Table1 when you delete row at Table1.
And you shouldn't call stmt.executeUpdate(foreignKey); each time you insert data to Table1, Table2. It should be done once when you describe the structure of your database.

I want to display foreign keys in one table from other tables, but I get foreign key mismatch error

I'm very new to SQL and I want the contracts_tb (query details below) is to display and link the foreign id keys referred from:
med_idref (referred from med_id (INTEGER), PRIMARY KEY o mediaadv_tb),
mediatitle_ref (title (TEXT), mediaadv_tb),
mediatype_red (mtype (TEXT), mediaadv_tb),
cus_idref (cus_id (INTEGER),PRIMARY KEY of customer_tb),
cus_companyref (referred from company (TEXT), in customer_tb)
All to be linked and displayed to contracts_tb. When I add/replace values from mediaadv_tb and customer_tb, I get this problem:
foreignkey mismatch
Also, do I have to make or assign a parent table?
Query:
DROP TABLE IF EXISTS customer_tb;
CREATE TABLE IF NOT EXISTS customer_tb (
cus_id INTEGER PRIMARY KEY,
company TEXT,
firstname TEXT,
middlename TEXT,
lastname TEXT,
gender TEXT,
dob TEXT,
dateregistered TEXT,
contactno TEXT,
emailaddress TEXT,
description TEXT,
refpic INTEGER,
cuspic BLOB
);
DROP TABLE IF EXISTS mediaadv_tb;
CREATE TABLE IF NOT EXISTS mediaadv_tb (
med_id INTEGER PRIMARY KEY,
mtype TEXT,
duration TEXT,
title TEXT,
dateadded TEXT,
desription TEXT,
previewimg BLOB,
filepath TEXT
);
DROP TABLE IF EXISTS contracts_tb;
CREATE TABLE IF NOT EXISTS contracts_tb (
contract_id INTEGER PRIMARY KEY,
customer_idref INTEGER REFERENCES customer_tb (cus_id),
media_idref INTEGER REFERENCES mediaadv_tb (med_id),
media_typeref TEXT REFERENCES mediaadv_tb(mtype),
media_titleref TEXT REFERENCES mediaadv_tb (title),
status TEXT,
priority TEXT,
dateadded TEXT,
dateexpiration TEXT,
amountpaid REAL,
arearofcoverage TEXT
);
Error :-
contracts_tb
mediaadv_tb
I believe that your issue is because the foreign keys defined that reference the media_typeref and the media_titleref columns are invalid as they do not have, or are part of a, UNIQUE indexes (no indexes). SQLite Foreign Key Support - 3. Required and Suggested Database Indexes
The referenced id columns, as they are INTEGER PRIMARY KEY, are implicitly UNIQUE indexes.
Furthermore the two columns (typeref and titleref) themself aren't even needed as the media_idref column would be used to identify the reference and thus would hold the respective values. Copying those values into the contracts table would be contrary to normalisation and may even create major headaches (e.g. if a value changed you'd have to find all other uses and also change them).
As such I'd suggest that the contracts_tb be created using :-
DROP TABLE IF EXISTS contracts_tb;
CREATE TABLE IF NOT EXISTS contracts_tb (
contract_id INTEGER PRIMARY KEY,
customer_idref INTEGER REFERENCES customer_tb (cus_id),
media_idref INTEGER REFERENCES mediaadv_tb (med_id),
status TEXT,
priority TEXT,
dateadded TEXT,
dateexpiration TEXT,
amountpaid REAL,
arearofcoverage TEXT
);
Re comment :-
What i'm making is a Java NetBeans SQLite database program, where by
using the Contracts frame, whevenr one makes a new contract, there
will be a combobox that restricts the user to only put the existing
ids or names that is referred in the contracts_tb then provides the
choices. Is it possible sir?
Yes.
More specifically:-
Assume that you have customers Fred, Bert and Harry (id's 1,2 and 3 respectively). And that you have mediaadv's M1, M2 and M3 (id's 10,11 and 12 (not 1,2 and 3 to help distinguish between mediaadv and customers)).
Additionally I'll assume the suggested contracts_tb table as opposed to the original in the question (i.e. 2 columns dropped as suggested)
The when inserting a new contract, you present a list (combobox) of the customers e.g.
Fred
Bert
Harry
(this list could be generated from a query such as:-
SELECT cus_id,firstname FROM customer_tb; i.e. all existing customers)
If you wanted Fred James Bloggs then you could use :-
SELECT cus_id,firstname||' '||middlename||'lastname' AS fullname FROM customer_tb;.
Likewise a list of the existing mediaadv could be generated from a query such as:-
SELECT med_id, description FROM mediaadv_tb; e.g.
so the combobox would have:-
M1
M2
M3
Now if the contract were for Bert (id 2) and M1 (id 10) then you build SQL something like :-
INSERT INTO contracts_tb VALUES(null,2,10,'the_status','the_priority','yyyy-mm-dd','yyyy-mm-dd',500,'the_coverage');
1st value is null i.e. no value, so as contract_id is an alias of the rowid it will be generated.
2 is the id of the customer (hence why cus_id was in the query as you need the id as it's the value you are going to store)
10 is the id of the mediaadv (again hence why med_id was in the query as you need the id as it's the value you are going to store).
the other values are what they should be.
Note the above use of INSERT requires that all columns be given. You can skip columns by specifying a list of the columns e.g. INSERT INTO contracts_tb (customer_idref,media_idref) VALUES(2,10);
As a customer with an cus_id of 2 (Bert) exists then the constraint that customer_idref is an existing id in the customer_tb is good/met and there is no conflict.
Likewise as there is a row in mediaadv_tb that has an med_id of 10 this constraint is good/met and there is no conflict.
However say the SQL were :-
INSERT INTO contracts_tb VALUES(null,2,100,'the_status','the_priority','yyyy-mm-dd','yyyy-mm-dd',500,'the_coverage');
Then as there is no med_id of 100 the constraint saying that media_idref must reference a value of 100 (in this instance) in the mediaadv_tb, column med_id, then the constraint will not be met and the insert will fail.
So again Yes, I believe that what you want is feasible.
Note a foreign key is only a constraint it doesn't bind/associate columns or join tables.

How to differentiate PrimaryKey and uniquekey Constraint in java

In both cases of PrimaryKey violation and uniqueKey violation, I see the same message, error code and sql state values.
When I run the insert query directly in the db, getting the same error message for both the cases. Only difference is the constraint name. we cannot rely on the constraint name all the time. How to differentiate the different types of SQL constraints violations?
try {
// create Db connection & sql insert into table statement
// stmt.executeUpdate("insert into mytable (A,B) .......")
// mytable has primary key on column A and unique key on column B
}catch(Exception e){
System.out.println(">>>>>>>>>> get Message :: " + e.getMessage());
System.out.println(">>>>>>>>>> get err code:: " + ((SQLException)e).getErrorCode());
System.out.println(">>>>>>>>>> get sql state:: " + ((SQLException)e).getSQLState());
}
Test 1:
>>>>>>>>>> get Message :: ORA-00001: unique constraint (TABLE_NAME.UK) violated
>>>>>>>>>> get err code:: 1
>>>>>>>>>> get sql state:: 23000
Test 2:
>>>>>>>>>> get Message :: ORA-00001: unique constraint (TABLE_NAME.PK) violated
>>>>>>>>>> get err code:: 1
>>>>>>>>>> get sql state:: 23000
we cannot rely on the constraint name all the time
And why ?
The constraint name has to be unique.
Consequently to distinguish programmatically from a SQLException a constraint violation from another one which both are the same constraint type and so have the same error code, you could check the constraint name.
If you don't want to use this way, you have to manually check that the data to insert doesn't violate the constraints set on the table.
It is also a way of proceeding but it will be more expensive to perform systematically a check before inserting.
If you know the constraint name and the schema owner, you can look up the constraint type from the all_constraints table.
For example:
select constraint_type from all constraints where owner='<your schema owner>'
and constraint_name = '<constraint name returned in your error>'
Look here for the various constraint type codes - https://docs.oracle.com/cd/B19306_01/server.102/b14237/statviews_1037.htm#i1576022
Given the name (PK or UK) can you find the meta data about that name?
For example, Oracle has the the ALL_CONSTRAINTS and ALL_INDEXES tables. ALL_CONSTRAINTShas a constraint_type column where P = primary key. ALL_INDEXES has a uniqueness column with values of UNIQUE or NONUNIQUE.
Hopefully your database has something similar.

Error executing Create table statement in Java?

I am trying to create 2 tables in MySql using Java JDBC,the first one runs fine but I get an error when I execute the second create table command. The problem looks like in the Foreign key definition not sure what's missing ?
Error :
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:
You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server
version for the right syntax to use near 'FOREIGN KEY(UniqueBusID)
REFERENCES BUS_3_CLEARBROOK_UFV_GOLINE_TO_UFV_BusDetai' at line 1
Code
String table_UniqueBusNameTimings = BusDetails+"_BusTimings";
String timings= "Timings";
String dayofweek = "DayOfWeek";
String FuniqueBusID = "UniqueBusID";
String table_UniqueBusNameDetails = BusDetails+"_BusDetails";
String PuniqueBusID = "UniqueBusID";
String StopNames = "StopNames" ;
String sql1 = "CREATE TABLE "+table_UniqueBusNameDetails+
"(UniqueBusID VARCHAR(255) not NULL, " +
" StopNames VARCHAR(1000), " +
" PRIMARY KEY ( UniqueBusID ))";
String sql2 = "CREATE TABLE "+table_UniqueBusNameTimings+
"(Timings VARCHAR(255) , " +
" DayOfWeek VARCHAR(25), " +
" UniqueBusID VARCHAR(255) "+
" FOREIGN KEY(UniqueBusID) REFERENCES "+table_UniqueBusNameDetails+"(UniqueBusID))";
stmt.executeUpdate(sql1);
stmt.executeUpdate(sql2);
You have a comma missing after UniqueBusID VARCHAR(255). Just change it to UniqueBusID VARCHAR(255), and your code shall be fine.
For details on syntax related to CREATE TABLE with FOREIGN KEY, you can explore this page: http://www.w3schools.com/sql/sql_foreignkey.asp
We should use CREATE TABLE IF NOT EXISTS... then if we are having foreign key relation then we should use SET FOREIGN_KEY_CHECKS=0; Finally we will execute a batch what having all the statement and then commit.
Every attribute like column, index, foreign key etc. should be seprated by comma ',' in table creation syntax. so here a comma missing after UniqueBusID VARCHAR(255). It will be fine after adding comma here.
#Suzon: We should not set foreign_key_checks=0 specially during creating table or adding any constraint at it will skip any constraint checking by mysql and create major issue in database. We can use it only we are sure its impact for example we want to delete some rows from master table even child table contains corresponding rows and we are fine with this etc.

Categories