How to add unique index and delete duplicates - sql

I want to add a unique index in my DB, but some data has already been duplicated.
I am trying out this using a test table before applying to the actual one.
It seems that if there are duplicated rows then we wouldn't be able to add the unique constraint.
I want to add the unique constraint and do not care which row gets deleted.
When I run the following
ALTER TABLE test_user ADD CONSTRAINT test_constraint UNIQUE (personid);
I am getting this error
ERROR: could not create unique index "test_constraint"
DETAIL: Key (personid)=(1) is duplicated.
SQL state: 23505
What would be the best way to achieve this? I am using Postgres as the DB

Create a copy of the table eliminating duplicates:
CREATE TABLE test_user_new (LIKE test_user);
INSERT INTO test_user_new
SELECT DISTINCT ON (id) *
FROM test_user;
ALTER TABLE test_user_new PRIMARY KEY (personid);
Then replace the original table:
DROP TABLE test_user;
ALTER TABLE test_user_new RENAME TO test_user;

Related

Making unique index case-insensitive

I have a unique index on the table and I need to make it case-insensitive, because I started getting duplicates in that table:
TEST
Test
TeSt
To fix the issue I was trying to drop existing index and re-create it:
ALTER TABLE table1 drop constraint test_uk1;
DROP INDEX test_uk1;
CREATE UNIQUE INDEX test_uk1 ON table1(UPPER(column1));
ALTER TABLE table1 ADD CONSTRAINT test_uk1 UNIQUE (column1) USING INDEX test_uk1 ENABLE VALIDATE;
I got an error ORA-14196: Specified index cannot be used to enforce the constraint. on the last statement.
Is there a better way to accomplish this with Oracle?
You can use a virtual column to normalise the case of the string and then put the unique constraint on the virtual column:
CREATE TABLE table_name (
value VARCHAR2(20),
uvalue VARCHAR2(20)
GENERATED ALWAYS AS (UPPER(value))
CONSTRAINT table_name__uvalue__u UNIQUE
);
Then:
INSERT INTO table_name (value) VALUES ('abc');
INSERT INTO table_name (value) VALUES ('aBc');
Inserts one row and the second statement fails with:
ORA-00001: unique constraint (FIDDLE_QDGWKZFBAWPLSRVHJNHN.TABLE_NAME__UVALUE__U) violated
db<>fiddle here
You need not to ALTER TABLE table1 ADD CONSTRAINT ..., the definition of the functional based index is enough for the creation of the unique constraint.
It is also wrong, as you use UNIQUE (column1) which you do not want, so simple skip this statement.
CREATE UNIQUE INDEX test_uk1 ON table1(UPPER(column1));
insert into table1 (column1) values('x');
insert into table1 (column1) values('X');
ORA-00001: unique constraint (XXX.TEST_UK1) violated
Even independently of the DBMS (Oracle, SQL Server, DB2, Vertica, PostgreSQL, you name them), Indexes live and die with the fact that data is not modified/derived before the index or the optimisation taking advantage of the index is applied.
So your approach is doomed, as far as I can tell.
Try this:
ALTER TABLE table1 ADD column1_u DEFAULT UPPER(column1);
CREATE UNIQUE INDEX test_uk1 ON table1(column1_u);
ALTER TABLE table1 ADD CONSTRAINT test_uk1 UNIQUE(column1_u)
USING INDEX test_uk1 ENABLE VALIDATE;
I know, it's a long transaction if your table is big, as you need to shuffle half the tablespace, but it's worth it ..

Unable to drop unique key

Hi I have a table that contains Unique key on of the columns. How do I delete the unique key from the that column. I am using Sql Server 2008
When I use the following command I get error
ALTER table [Contact].[FatcaQuestionaire]
DROP CONSTRAINT UK_FatcaQuestionaire_Contact
'UK_FatcaQuestionaire_Contact' is not a constraint.

Error Adding Multiple FK Relationship in SQL Server 2008

Consider we have two tables ProductType and ProductSizeGroup as below
ProductType
Id
Name
MaleSizeGroupId
FemaleSizeGroupId
ChildSizeGroupId
ProductSizeGroup
Id
Name
Each of MaleSizeGroupId, FemaleSizeGroupId and ChildSizeGroupId fields should be FKs to ProductSizeGroup.Id.
I add one using the following statement:
ALTER TABLE [dbo].[ProductType]
WITH CHECK ADD CONSTRAINT
[FK_ProductType_ProductSizeGroup_Male] FOREIGN KEY([MaleGroupId])
REFERENCES [dbo].[ProductSizeGroup] ([Id])
This works fine. I try to add the next using
ALTER TABLE [dbo].[ProductType]
WITH CHECK ADD CONSTRAINT
[FK_ProductType_ProductSizeGroup_Female] FOREIGN KEY([FemaleGroupId])
REFERENCES [dbo].[ProductSizeGroup] ([Id])
But I get the error:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_ProductType_ProductSizeGroup_Female". The conflict
occurred in database "dbname", table "dbo.ProductSizeGroup", column
'Id'.
So there is conflict.. but what conflict? What should I be looking for?
That just means: there are rows in your table ProductType that have values in the FemaleGroupId column which do not exist in the referenced table (ProductSizeGroup).
It's not a problem per se - you can totally have multiple columns going from one table to another.
The problem is with the existing data - you have data in there that doesn't live up to that FK constraint. Fix that data and you should be fine.
To find those offending rows, use a query like this:
SELECT *
FROM [dbo].[ProductType]
WHERE FemaleGroupId NOT IN (SELECT DISTINCT Id FROM [dbo].[ProductSizeGroup])
That will list all offending rows - update their attribute and get going again!

SQL: Create new column with default, unique value

I have added a new column, called Ordinal, to a table called Activity. The problem is that I gave it a UNIQUE constraint, set it to allow NULL (though this I won't want in the end.. I just needed to set it to that to get a little farther with the script), and did not give it a default value. I'm now running a RedGate SQL Compare script that was generated by comparing this table to a version of the Activity table that does not have the column. But I'm getting the following error:
The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for the object name 'iwt.Activity' and the index name 'IX_Activity'. The duplicate key value is (1).
So based on my research, it's trying to create a unique key constraint on the Ordinal column, but NULL is not unique. So my next step was to give it a unique value of 1 just to let the script pass. But 1 isn't going to be unique either. So, finally, my question:
Preferably in SQL Server Management Studio, how do I set a column as having a unique default value? Isn't that what I would need to create this constraint?
Thanks.
try this:
NULL will be the first constraint when you create the column.
UNIQUE will be as add constraint, you should add the second constraint.
they can run on this order with no problem (tested):
--first constraint
alter table Table_Name
add Column_Name int null
--second constraint
alter table Table_Name
add constraint Constraint_Name unique (Column_Name)
In my example :
PaymentGatewayHash is column
Cart is a table
--first query
alter table Cart
add PaymentGatewayHash NVARCHAR(20) null
--second query
CREATE UNIQUE INDEX PaymentGatewayHashUnique
ON Cart (PaymentGatewayHash)
WHERE PaymentGatewayHash IS NOT NULL
I just tested that :D

Does making a column unique force an index to be created?

In SQL Server 2005+ (I use both), does adding the UNIQUE constraint to a column automatically create an index, or should I still CREATE INDEX?
See this MSDN article:
The Database Engine automatically
creates a UNIQUE index to enforce the
uniqueness requirement of the UNIQUE
constraint.
If you do create an index, you'll end up with two indexes, as this example demonstrates:
create table TestTable (id int)
alter table TestTable add constraint unique_id unique (id)
create unique index ix_TestTable_id on TestTable (id)
select * from sys.indexes where [object_id] = object_id('TestTable')
This will display two unique indexes on TestTable; and the HEAP that represents the table itself.
Yes, it does.
In fact, you can even create a CLUSTERED UNIQUE CONSTRAINT:
ALTER TABLE mytable ADD CONSTRAINT UX_mytable_col1 UNIQUE CLUSTERED (col1)
, which will make the table to be clustered on col1.
Almost all databases create an index for UNIQUE CONSTRAINT, otherwise it would be very hard to maintain it.
Oracle doesn't even distinguish between UNIQUE CONSTRAINT and UNIQUE INDEX: one command is just a synonym for another.
The only difference in Oracle is that a UNIQUE INDEX should have a user-supplied name, while a UNIQUE CONSTRAINT may be created with a system-generated name:
ALTER TABLE mytable MODIFY col1 UNIQUE
This will create an index called SYS_CXXXXXX.
An index is created when you add a unique constraint:
Reference -- see the second paragraph.
When a UNIQUE constraint is added to
an existing column or columns in the
table, by default, the Database Engine
examines the existing data in the
columns to make sure all values are
unique. If a UNIQUE constraint is
added to a column that has duplicated
values, the Database Engine returns an
error and does not add the constraint.
The Database Engine automatically
creates a UNIQUE index to enforce the
uniqueness requirement of the UNIQUE
constraint. Therefore, if an attempt
to insert a duplicate row is made, the
Database Engine returns an error
message that states the UNIQUE
constraint has been violated and does
not add the row to the table. Unless a
clustered index is explicitly
specified, a unique, nonclustered
index is created by default to enforce
the UNIQUE constraint.