Reputation: 199
I have a (oracle) database table with column called name VARCHAR
. I need to update the table to add a unique constraint on this column. But before I can add the unique constraint I need to ensure that all the values in the column are unique. I want to achieve this by adding suffixes like -1
, -2
, etc in case of duplicate entries.
For example if there are 3 rows having duplicate values in the name column, let's say the value is Hari
, I want to change the values as Hari
, Hari-1
, Hari-2
.
How can I achieve this using SQL / PLSQL only?
Upvotes: 0
Views: 83
Reputation: 9083
I have used the example that @Tim Biegeleisen provided and adjusted his answer to get you the result you are asking for.
SELECT
name,
TO_CHAR(name ||
case
when ROW_NUMBER() OVER (PARTITION BY name ORDER BY id) = 1 then ''
else to_char ('-' || (ROW_NUMBER() OVER (PARTITION BY name ORDER BY id)-1))
end) name_new
FROM yourTable
ORDER BY name;
Demo: https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=8d8a1b3f5146b018f92a4c344ed40414
Upvotes: 1
Reputation: 168416
You can use MERGE
statement and the ROW_NUMBER()
analytic function:
MERGE INTO table_name dst
USING (
SELECT ROWID AS rid,
name,
ROW_NUMBER() OVER ( PARTITION BY name ORDER BY ROWNUM ) AS rn
FROM table_name
) src
ON ( dst.ROWID = src.rid )
WHEN MATCHED THEN
UPDATE SET name = CASE rn
WHEN 1
THEN src.name
ELSE src.name || '-' || (rn - 1)
END;
Then use:
ALTER TABLE table_name ADD CONSTRAINT table_name__name__u UNIQUE( name );
To create a named unique constraint on the column.
Oracle Setup:
CREATE TABLE table_name ( name ) AS
SELECT 'Hari' FROM DUAL UNION ALL
SELECT 'Hari' FROM DUAL UNION ALL
SELECT 'Hari' FROM DUAL UNION ALL
SELECT 'Alice' FROM DUAL UNION ALL
SELECT 'Bob' FROM DUAL UNION ALL
SELECT 'Bob' FROM DUAL UNION ALL
SELECT 'Charlie' FROM DUAL;
Output:
SELECT * FROM table_name;
| NAME | | :------ | | Hari | | Hari-1 | | Hari-2 | | Alice | | Bob | | Bob-1 | | Charlie |
db<>fiddle here
Upvotes: 1
Reputation: 522471
I suggest just using ROW_NUMBER()
here to generate the identifier you want:
SELECT
name,
TO_CHAR(name || '-' || ROW_NUMBER() OVER (PARTITION BY name ORDER BY id)) AS name_new
FROM yourTable
ORDER BY name;
Upvotes: 1