Sql 2 primary keys remove rows where 1 primary key is duplicated - sql

I ve a Sql table (mariaDB) with 2 Primary keys. I want to remove the rows where the first primary key is duplicated.(yes i know that primary keys cant be duplicated but with 2 Primary keys they work like a touple so that it is possible, but in my case not wanted) example:
id(pk)
name(pk)
smth
smth else
1
a
1234
qwerty
1
b
4567
asdf
and i want to remove the 2nd line cause the id key is duplicated.
tried:
almost any delete query with row count
the query i tried last:
WITH CTE AS
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) AS RN
FROM product_names
)
DELETE FROM CTE WHERE RN<>1

To clarify the definition, you cannot have two primary key in a table. But the primary key of your table is composed of two columns.
To improve your schema, you may want to alter your table so that the primary key is only based on first column. However, depending on the database engine, it can be usefule to keep your composite key. It may speed up query which retrieve the second column only from the primary key. In that case you may want to add a unique clause to the first colume of your primary key.
To cleanup your table you can use that, but beware it doesn't have a filter on the second column, meaning any column with the same id can be deleted depending on its order.
WITH duplicated AS (
SELECT id, name, row_number() OVER (PARTITION BY a) row_number
FROM product_names
ORDER BY name
)
DELETE FROM product_names
WHERE (a, b) IN (SELECT a, b FROM duplicated WHERE row_number > 1);

Related

How to create a unique index between two columns for all rows in SQL Server 2019?

I am trying to create a constraint or a check to make sure that sourceLocationId and destinationLocationId can never be the same.
I have source being unique, and destination being unique and also unique between source and destination. But this can still happen.
Same source and destination in two different rows
Is there any way to do this where essentially sourceLocationId is completely unique throughout the two columns and the same for destinationLocationId?
It's a rather strange requirement, as it means that once a value has appeared as either a SourceLocationId or DestinationLocationId it cannot appear again. Normally you only want to ensure that pairs of them cannot duplicate, and that the two columns cannot be the same on the same row.
Be that as it may: you cannot do this in SQL on a single table. A primary or unique constraint can only be on a single column, or on combinations of columns, not any of two columns.
You need to normalize out your data into separate rows
CREATE TABLE TurretLocation (
LocationId int IDENTITY PRIMARY KEY,
TurretId int NOT NULL REFERENCES Turret (TurretId),
IsDestination bit NOT NULL
);
To get your original table, simply group by TurretId
SELECT
TurretId,
SourceLocationId = MIN(CASE WHEN IsDestination = 0 THEN LocationId END),
DestinationLocationId = MIN(CASE WHEN IsDestination = 1 THEN LocationId END)
FROM TurretLocation;

How can I modify the primary key when I deleting a specific row?

Let say I have 7 row in my database and the primary key each row is 1,2,3,4,5,6,7. Now let say I deleted the third row, the primary key each row would be something like this 1,2,4,5,6,7 As you noticed the 3 was removed. I want them like this 1,2,3,4,5,6 the row with a primary key 4 is now become 3 and the 5 is now become 4 and so on.
And another one, let say I deleted the 5th row again with a primary key 5 and then after that the primary key each row would be like this 1,2,3,4,6 Now I want them all like this again 1,2,3,4,5 the row with primary key 6 become now 5. I JUST WANT EVERY TIME I DELETE A ROW I all the primary keys are in orderenter image description here
You can update you primary key column based on row number after the deletion. Attaching sample code considering your table as "customer" and key column is "Cust_id".
update customer cust
JOIN
(
SELECT ROW_NUMBER() OVER (
ORDER BY Cust_id
) row_num, Cust_id
FROM customer
)AS rw_num
ON cust.Cust_ID = rw_num.Cust_ID
set cust.Cust_ID=rw_num.row_num

Best way to delete duplicate rows in an intersection table based on foreign key column

I'm looking for a way to delete dupicate rows from an intersection table based on a foreign key from one of the tables from the opposite ends of the intersection table. For the sake of clarity, I'll say based on a foreign key value from the intersection table on the left 'tableA'.
CREATE TABLE tableA
(
link varchar(64) NOT NULL PRIMARY KEY,
name varchar(64) NOT NULL
)
CREATE TABLE tableB
(
link varchar(64) NOT NULL PRIMARY KEY,
name varchar(64) NOT NULL
)
CREATE TABLE tableA_AND_tableB--Intersection Table
(
link varchar(64) NOT NULL PRIMARY KEY,
LtableA varchar(64) references tableA(link),
LtableB varchar(64) references tableB(link)
)
Basically, I want to delete all duplicate rows in the intersection table based on the 'LtableA' foreign key field. For instance: Say I have 20 duplicates of 'LtableA = id20140722' in 'tableA_AND_tableB', how do I go about deleting all the rows matching the value 'id20140722' in 'tableA_AND_tableB' without affecting anything else?
Hope my question makes sense.
Delete from tableA_AND_tableB where LtableA = 'id20140722'
This will remove all rows from that table sepcifically with that ID. Alternatively you can see this question for something that will delete all duplicates. Though that answer will keep either the first or last duplicate.
If you want to delete duplicates but still keep one distinct copy of each row:
WITH t AS (
SELECT ROW_NUMBER() OVER(PARTITION BY LtableA, LtableB ORDER BY link) row_num
FROM tableA_AND_tableB
)
DELETE
FROM t
WHERE row_num > 1
AND LtableA = 'id20140722'

Copy data from a table, into the same table with a different key

I was curious if it was possible to take data from a table, and duplicate it but assign a new primary key
for example, I wish to take data that has a column "question_id" which acts as the unique key for the table, and copy all of the data from the table with that question_id to the same table but with a new question_id.
any thoughts as to if this is possible using SQL?
my database is an ingres database
thanks in advance
Sure, something like this should work:
INSERT INTO YourTable (Question_Id, OtherField,...)
SELECT SomeNewQuestionId, OtherField,...
FROM YourTable
WHERE Question_Id = SomeQuestionId
Just replace SomeQuestionId and SomeNewQuestionId with the appropriate values.
It's a simple select query.
insert into mytable
(field2, field3, etc)
select field2, field3, etc
from mytable
where whatever.
This assumes that neither fields 2 nor 3 are the primary key, and that you have an autoincrement table.
Fast forward two years.... :)
I think this is the best and simplest way to do this. Inserting a row of data from the same table with a primary key will result in error because primary keys are unique for each row: Let question_id = 100.
INSERT INTO MyTable SELECT * FROM MyTable Where question_id=100;
In PostgreSQL:
ERROR: duplicate key value violates unique constraint "MyTable_pkey"
DETAIL: Key (question_id)=(100) already exists.
It is very simple to avoid the duplicate key value:
INSERT INTO MyTable SELECT (SELECT MAX(question_id)+1),Column1,Column2,etc FROM MyTable Where question_id=100;
By using MAX(question_id)+1, you are incrementing the maximum value of MyTable's question_id primary key, then add/copy the data to a new row with a unique question_id value.

Generating unique foreign key tuples

I have a table like this:
CREATE Table tblClassProperty (
ClassPropertyID integer IDENTITY(1,1) PRIMARY KEY,
Active bit DEFAULT 0 NOT NULL,
DEL bit DEFAULT 0 NOT NULL,
FINAL bit DEFAULT 0 NOT NULL,
Locked bit DEFAULT 0 NOT NULL,
_Project integer FOREIGN KEY REFERENCES tblProject(ProjectID),
_Property integer FOREIGN KEY REFERENCES tblProperty(PropertyID),
_Class integer FOREIGN KEY REFERENCES tblClass(ClassID)
CONSTRAINT CClassProperty UNIQUE(_Project,_Property,_Class))
I am migrating data from an old table (in another DB) into this one. For the most of the columns I am just copying the data from the other table. The foreign key columns don't exist in the old DB, they are just random values linked with the corresponding tables in the new DB. For your solution please take it for granted that the values for the columns _Project, _Property and _Class need to be generated the way they are now (with the SELECT TOP 1 ...)
INSERT INTO ClassDB..tblClassProperty (Active, DEL, FINAL, Locked,
_Project, _Property, _Class)
SELECT Active, DEL, FINAL, Locked,
(SELECT TOP 1 ProjectID FROM ClassDB..tblProject ORDER BY NEWID()),
(SELECT TOP 1 PropertyID FROM ClassDB..tblProperty ORDER BY NEWID()),
(SELECT TOP 1 ClassID FROM ClassDB..tblClass ORDER BY NEWID()),
FROM ClassDB_Access..tblClassProperty
Now, the INSERT INTO script won't run because of the unique constraint, and the constraint must stay as it is.
My question: I need a script that copies the existing columns, generates the foreign keys as above, BUT the generated values for the tuple (_Project, _Property, _Class) will be unique as per constraint.
The script has to run in SQL Server 2008 R2, and in the future also in Oracle.
You might cross join all three columns, assign random row numbers to them and join them back to tblClassproperty augmented by row_number:
; with randomized as (
select a.ProjectID,
b.PropertyID,
c.ClassID,
row_number() over(order by newid()) rn
from ClassDB..tblProject a
cross join ClassDB..tblProperty b
cross join ClassDB..tblClass c
),
ordered as (
select Active, DEL, FINAL, Locked,
row_number() over (order by newid()) rn
from ClassDB_Access..tblClassProperty
)
INSERT INTO ClassDB..tblClassProperty (Active, DEL, FINAL, Locked,
_Project, _Property, _Class)
select ordered.Active, ordered.DEL, ordered.FINAL, ordered.Locked,
randomized.projectID, randomized.PropertyID, randomized.ClassID
from ordered
inner join randomized
on ordered.rn = randomized.rn
This will not work in Oracle without reshuffling cte parts - or you might rewrite this using derived tables for instant compatibility.
Disclaimer: Other than syntax check this is not tested. Performance might be awful.
Edit: Forgot to mention that, in case of duplicate values in IDs, you might want to do distinct before cross joins.