I've written this java servlet which inserts items into a table however it fails. I think it might be due to my insertion and deleting which got me in trouble some how. The java servlet runs an insert statement into sql server. In my error log, it says:
com.microsoft.sqlserver.jdbc.sqlserverexception: cannot insert duplicate key row in object 'dbo.timitem' with unique index 'XAK1timitem'.
any ideas?
UPDATE: i found there is an index called "XAK1timItem (Unique, Non-Clustered)" which I'm not really sure what to do with.. hope this helps the question.
The unique index will enforce uniqueness for the combination of the rows included in the index. So if you have a row in the database which has, for the indexed column, values equal to those you are trying to insert, you will get an error back from the database.
The AK part indicates that this is an alternative key which probably means that the table has a regular primary key, and does not need to rely on the AK for unique identification of a row.
Some options:
drop the index if not needed
add another column to the unique index
make the index not unique, so that it allows duplicate values
check if there is already a row that matches the one you are about to
insert and abort the insert, but I guess you don't want to do this
Related
I'm using unique constraint for avoiding duplicates except null values because this column can remains null (it's not mandatory field but it helps in search like search by email e.t.c)
In above situation, Is it is right to choose unique constraint or not?
Alternative
As unique allows only one null value, so it is possible to generate different default values for unique constraint? i-e unique for each row.
You tagged the question both sqlite and mysql, so I'll cover both.
SQLite
In SQLite, a UNIQUE constraint will work as you want.
The documentation for UNIQUE constraint says:
For the purposes of UNIQUE constraints, NULL values are considered distinct from all other values, including other NULLs.
The documentation for CREATE INDEX says:
If the UNIQUE keyword appears between CREATE and INDEX then duplicate index entries are not allowed. Any attempt to insert a duplicate entry will result in an error. For the purposes of unique indices, all NULL values are considered different from all other NULL values and are thus unique. This is one of the two possible interpretations of the SQL-92 standard (the language in the standard is ambiguous) and is the interpretation followed by PostgreSQL, MySQL, Firebird, and Oracle. Informix and Microsoft SQL Server follow the other interpretation of the standard.
However, in most other databases, the columns of a UNIQUE constraint cannot be NULL, so I would recommend using a UNIQUE INDEX instead, for consistency, and so as not to confuse people.
MySQL
In MySQL, a UNIQUE constraint will work as you want.
The documentation for Unique Indexes says:
A UNIQUE index permits multiple NULL values for columns that can contain NULL.
A UNIQUE KEY is a synonym for a UNIQUE INDEX.
SQL Server
As mentioned in the SQLite documentation, Microsoft SQL Server follow a different interpretation of NULL handling for UNIQUE indexes.
The documentation for UNIQUE INDEX says:
Columns that are used in a unique index should be set to NOT NULL, because multiple null values are considered duplicates when a unique index is created.
To work around that, use a filtered index, e.g.
CREATE UNIQUE INDEX Person_Email
ON Person ( Email )
WHERE Email IS NOT NULL;
You can use a trick with generated columns. Something like this:
alter table t add unique_val as
( concat(coalesce(col, ''), ':', (case when col is null then pk end)) ) unique;
Where pk is the primary key column.
This replaces the NULL values with something known to be unique on each row.
The below insert statement is not working saying:unique primary key violated ora-0001. Do you know why it is not working ?
primary key is the seq id
INSERT INTO VITA_TRANSACTION ( VTR_SEQ_ID,VTR_QUELLE_SEQ_ID,VTR_QUELLE,
VTR_PROVIS_EXPORT_LOG_ID,VTR_DWH_EXPORT_LOG_ID,VTR_SYS_DATE,
VTR_PROCESSSTATE,VTR_IMEI_NR,VTR_IMEI_ZUORDNUNG,VTR_ZUORDNUNG_DATE,
VTR_IMEI_KNZ,VTR_SUBSCRIBER_NO,VTR_INSERT_TYPE,VTR_ERFASSUNG_DATUM,
VTR_VOID_ACTIVATE,VTR_QUELLSYSTEM,VTR_VORGANG,VTR_STORNO,VTR_SALES_PRICE,
VTR_ARTICLE_NO)
values (SEQ_VITA_TRANSACTION.nextval,418912,'M-ABVK',null,null,sysdate,
'UM','352523003062648','352523003062648',
to_date('20160118194708', 'YYYYMMDDhh24miss'),null,32927785,'AK',
to_date('20160118000000', 'YYYYMMDDhh24miss'),'60000661','Activate',
'Act','N',2000,'123123')
PK violation means that your table already contains the id that your sequence is creating. Try check the value of SEQ_VITA_TRANSACTION.nextval and the max(VTR_SEQ_ID) from VITA_TRANSACTION:
select 'seq', SEQ_VITA_TRANSACTION.nextval from dual
union all
select 'tab', max(VTR_SEQ_ID) from VITA_TRANSACTION
This may not the exact answer to your question but I am trying to debug your problem.
ORA-0000
1: unique constraint (string.string) violated
Cause: An UPDATE or INSERT statement attempted to insert a duplicate key. For Trusted Oracle configured in DBMS MAC mode, you may see this message if a duplicate entry exists at a different level.
So duplicate entry already exists in VITA_TRANSACTION table.
First you should retrieve the current value of the sequence without increment it
Sample
SELECT last_number
FROM all_sequences
WHERE sequence_owner = '<sequence owner>'
AND sequence_name = '<sequence_name>';
For detail follow this question How to retrieve the current value of an oracle sequence without increment it?
Then do a search in the VITA_TRANSACTION where VTR_SEQ_ID= retrieved current value + 1
I am quite sure you will get one row.Now to avoid this error you can increment your sequence value by executing the below sql.
select SEQ_VITA_TRANSACTION.nextval from dual;
It will increment the value of your current sequence by 1(if your sequence INCREMENT BY 1) . Then try to again execute your insert query.
Primary Key violation usually occurs if you are inserting already exist values in the table. So you can check the records on the table VITA_TRANSACTION for the next sequence i.e SEQ_VITA_TRANSACTION.nextval, you can use following query:
Select
count(*)
From **VITA_TRANSACTION**
where
VTR_SEQ_ID = **SEQ_VITA_TRANSACTION.nextval**;
If the above query returns count as 1 then there is already a record for that sequence. Then try by increasing the sequence value or you can delete the record. It's your call.
Hope this answers your question.
I have mentioned a sequence generation strategy as IDENTITY on my entity class for the primary key of a table in AS400 system.
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "SEQNO")
private Integer seqNo;
The table's primary key column is defined as GENERATED ALWAYS AS IDENTITY in database.
SEQNO BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY(START WITH 1, INCREMENT BY 1)
My understanding of IDENTITY strategy is that it will leave the primary key generation responsibility to the table itself.
The problem that I am facing is that somehow in one environment, while inserting record in the table it gives me [SQL0803] Duplicate Key value specified.
Now there are couple of questions in my mind:
Is my understanding correct for #GeneratedValue(strategy=GenerationType.IDENTITY)?
In which scenario table will generate Duplicate key?
I figured out there are sequence values missing in the table, i.e. after 4, the sequence till 20 is missing and I do not know if someone manually deleted it or not, but could this be related to duplicate key generation?
YES. IDENTITY means use in-datastore features like "AUTO_INCREMENT", "SERIAL", "IDENTITY". So any INSERT should omit the IDENTITY column, and will pull the value back (into memory, for that object) after the INSERT is executed.
Should never get a duplicate key. Check the INSERT statement being used.
Some external process using the same table? Use the logs to see SQL and work it out.
I don't use JPA, but what you have seems reasonable to me.
As far as the DB2 for i side...
Are you sure you're getting the duplicate key error on the identity column? Are there no other columns defined as unique?
It is possible to have a duplicate key error on an identity column.
What you need to realize is that the next identity value is stored in the table object; not calculated on the fly. When I started using Identities, I got bit by a CMS package that routinely used CPYF to move data between newly created versions of a table. The new version of the table would have a next identity value of 1, even though there might be 100K records in it. (the package has since gotten smarter :) But the point remains that CPYF for instance, doesn't play nice with identity columns.
Additionally, it is possible to override the GENERATED ALWAYS via the OVERRIDING SYSTEM VALUE or OVERRIDING USER VALUE clauses of the INSERT statement. But inserting with an override has no effect on the stored next identity value. I suppose one could consider CPYF as using OVERRIDING SYSTEM VALUE
Now, as far as your missing identities...
Data was deleted
Data was copied in with overridden identities
Somebody ALTER TABLE <...> ALTER COLUMN <...> RESTART WITH
You lost the use of some values
Let me explain #4. For performance reasons, DB2 for i by default will cache 20 identity values for a process to use. So if you have two processes adding records, one will get values 1-20 the other 20-40. This allows both process to insert concurrently. However, if process 1 only inserts 10 records, then identity values 11-20 will be lost. If you absolutely must have continuous identity values, then specify NO CACHE during the creation of the identity.
create table test
myid int generated always
as identity
(start with 1, increment by 1, no cache)
Finally, with respect to the caching of identity values. While confirming a few things for this answer, I noticed that the use of ALTER TABLE to add a new column seemed to cause a loss of the cached values. I inserted 3 rows, did the alter table and the next row got an identity value of 21.
I have 2 tables user and userinfo. userinfo table contains user_id(id of user table) column which has UNIQUE constraint.
now i have 2users(primaryUser and secondaryUser) which has records in user and userInfo tables.
The primaryInfo object contains primaryUserId and secondaryInfo object contains secondaryUserId
I want to swap the userinfo data of primaryUser to secondaryUser and viceversa. I am doing like this
primaryInfo.setUserId(secondaryUser.getId());
secondaryInfo.setUserId(primaryUser.getId());
session.update(primaryInfo);
session.update(secondaryInfo);
but when commiting the transaction it is giving error like
ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper:147 ERROR: duplicate key value violates unique constraint "user_infos_unique_user"
Detail: Key (ui_user_id)=(52560087) already exists.
can you please tell how to do this.. Thanks
You can use the DEFERRABLE and INITIALLY DEFERRED properties on the constraint and update both records in a single transaction. DEFERRED means the constraint will not be evaluated until the transaction is commited -- at which time it should be valid again.
However: I have not figured out how to use Hibernate annotations to specify the DEFERRED properties, so you will have to use LiquiBase to maintain the database schema (not a bad idea anyway.) (Or use "raw" SQL which is not so good an idea.)
See this question for more about the annotations (alas I cannot use LiquiBase on the project I ask about there.)
For Oracle database you can create next unique constraint with special attributes 'DEFERRABLE INITIALLY DEFERRED':
ALTER TABLE table_name ADD CONSTRAINT constraint_name UNIQUE (table_field) DEFERRABLE INITIALLY DEFERRED
A possible trick to work around the unique constraint is to do 3 updates:
update row A with a value for the column that no other row can use. NULL may be used if not forbidden by a not-NULL constraint, otherwise 0 if not forbidden and assuming it's an integer, otherwise a negative value.
then update row B with its final value (the previous value from row A)
then update row A with its real final value (the previous value from row B)
As error Shows:
there is a unique constraint on userInfo table. that means user must be unique. So If you wnat to swipe the two user Id. you have to perform following steps
1. Remove the constraint
2. Swap two id's(same code as you currently have)
3. Add Constaint.
I have counter for unique column in my table. Now I have list where I have column name (which is unique) and counter (which contains some integer value). I know that it is possible to insert multiple lines, I just could make query containing all those items on the list, but problem is that if there is already data in unique field.
In that case there is already this name and it has counter value, in this case I need to sum existing counter value to added alue and update that row. Is there any way to make all this with one Sql query? I use MySQL database and Java.
INSERT ON DUPLICATE KEY UPDATE
is the syntax you're looking for.
See here.