Confused on ERROR 1060 "Duplicate column name" - mysql

I'm trying to join multiple tables to have a view that can act as a report, but I'm confused as to why the I'm getting the MySQL ERROR 1060 (42S21): Duplicate column name 'storeNum'
I have tried using Left Join as from what I understand it looks for the same columns and then joins the tables based on the shared column where the columns that are joined are the ones that differ between the table.
All of the tables are connected by a foreign key.
Create view AR_Report as
select * from AR Left JOIN fullStoreList ON
AR.storeNumber = fullStoreList.storeNum
Left JOIN AR_po ON AR.storeNumber = AR_po.storeNum
Left JOIN AR_call ON AR.storeNumber = AR_call.storeNum
Left JOIN AR_prep ON AR.storeNumber = AR_prep.storeNum;
Create table AR(workOrder varchar(10)
primary key unique not null,
storeNumber int UNIQUE, FOREIGN KEY (storeNumber)
REFERENCES fullStoreList (storeNum));
// where all tables should feed into
Create table AR_call(storeNum int primary key unique not null, FOREIGN KEY (storeNum) REFERENCES AR (storeNumber), .... );
// AR_call, AR_prep and AR_po start like this
Create table fullStoreList( storeNum int primary key UNIQUE
not null, ...);
I can post the full create table statements, they are just really long.
I was expecting the view to have all the columns from the other tables be connected by the AR table without the storeNum being present multiple times.
I am very new to MySQL and am just trying to understand it more.

Related

Swap foreign keys in MySql

I have a MySql database with a Users table:
create table Users
(
Id varchar(255) charset utf8mb4 not null primary key,
ProfileId int auto_increment,
#other fields
);
ProfileId field is used as a foreign key for many tables. E.g.:
create table Fingerprints
(
Id int auto_increment primary key,
ProfileId int null,
constraint FK_Fingerprints_Users_ProfileId
foreign key (ProfileId) references Users (ProfileId)
);
I have two Users records and want to swap their ProfileIds without any other changes. How can I do it? I would prefer not to drop foreign key constrain because the database is on production and there are a lot of related tables where I have to do that.
Update:
The data is the following:
User1: ProfileId = 1,
User2: ProfileId = 2
#the other field doesn't matter
I want to swap their profileIds, so user1 contained user2's data from the related table by foreign key and vise versa.
Presumably, you don't want to change the foreign key relationships (they are not defined as cascading) I would suggest that you change the other columns:
update users u join
users u2
on (u2.profileid, u.profileid) in ( (#id1, #id2), (#id2, id1) )
set u.id = u2.id,
u.others = u2.others;

Set foreign key values based on existing column data

I am in the middle of migrating an old (unnormalized) database to its new version.
Right now I have this intermediate result:
CREATE TABLE recipient(
id int NOT NULL AUTO_INCREMENT,
email VARCHAR(255),
PRIMARY KEY (id),
UNIQUE INDEX (`email`),
) ENGINE=INNODB;
CREATE TABLE comment(
# Right now this is always NULL:
fk_recipient INT,
# Temporary solution. Note that this field is NOT UNIQUE:
tmp_email VARCHAR(255) NOT NULL,
# ...
FOREIGN KEY (`fk_recipient`) REFERENCES recipient(id);
) ENGINE=INNODB;
Both tables are filled with correct data:
some million comments with the right tmp_email and fk_recipient = null in table comment (note: emails are not unique)
some hundred thousand UNIQUE email adresses in table recipient.
What I need to do:
I want to get rid of the comment.tmp_email column and instead point comment.fk_recipient to the appropriate row in table recipient.
My current approach (using PHP):
get all comments
iterate over all comments:
look up the right row in recipient table
set right foreign key
... DROP COLUMN tmp_email
This takes forever and made me wonder if there is no native MySQL way to do that?
The following workaround will do the job:
Create temporary foreign key on comment.tmp_email:
ALTER TABLE comment
ADD CONSTRAINT `tmpMailKey` FOREIGN KEY (`tmp_email`)
REFERENCES `recipient`(`email`);
Join the two tables on the temporary key and use the information to set the real foreign key:
UPDATE comment c
INNER JOIN recipient r
ON
c.tmp_email = r.email
AND c.tmp_email IS NOT NULL
SET c.fk_recipient = r.id;
Get rid of temporary foreign key (and the tmp column too):
ALTER TABLE `udw_v3`.`travelogue_guestbookentry`
DROP COLUMN `tmp_email`,
DROP INDEX `tmpMailKey`,
DROP FOREIGN KEY `tmpMailKey`;

MySql replace with multiple primary keys

I have a table which has three primary keys and references three other tables
Here is the table scheema:
CREATE TABLE IF NOT EXISTS training_matrix_reference(
employee INT NOT NULL,
training_matrix INT NOT NULL,
training_record INT UNSIGNED NOT NULL,
PRIMARY KEY (employee, training_matrix,training_record),
FOREIGN KEY (employee) REFERENCES employees(id),
FOREIGN KEY (training_matrix) REFERENCES training_matrix_courses(id),
FOREIGN KEY (training_record) REFERENCES training_records(m_id)
)
I'm trying to craft a REPLACE statement which updates the training_record column or training_matrix column or both columns or creates a new row if not exists, but I also need to check that the employee belongs to the same company.
Here's what I tried so far:
REPLACE INTO `training_matrix_reference`
( employee, training_matrix, training_record ) (
SELECT id, '5', '100'
FROM employees
WHERE id =22
AND company =64
)
So my theory was that this should have replaced the first row in the table, updating training_record to 100 but in fact it actually created a new row:
22 | 5 | 100
My guess is that this happened because training_record is a primary key?
But I'm not sure that removing the primary keys/references is the right way to go as this table is used as a many to many table in other queries.
Effectively what I'm trying to do is:
REPLACE INTO `training_matrix_reference`
( employee, training_matrix, training_record )
VALUES
(22,33,18)
WHERE
employee = 22
and training_matrix = 5
and training_record = 2189
But obviously a replace statement doesn't have a where clause.
I did check out these similar questions:
MySQL REPLACE INTO on multiple keys?
mysql REPLACE query with multiple primary keys
But unfortunately MySql is not my strong suit and I could really use some help.
I hope I explained things clearly, Thanks
The PRIMARY KEY of the training_matrix_reference table is the combination of three columns. The table doesn't have multiple primary keys, it has a single PRIMARY KEY.
The REPLACE syntax you have is equivalent to performing:
DELETE FROM training_matrix_reference
WHERE employee = 22
AND training_matrix = 5
AND training_record = 100
;
INSERT INTO training_matrix_reference (employee, training_matrix, training_record)
VALUES (22, 5, 100);
;
The DELETE action only removes rows where the entire primary key is matched. Given the information you provided, we'd expect a row to be added to the table.
Did you have a question?
you should make a joining table between (employee, training_matrix_reference)
or dispense at lest one relation

Getting the affected rows when altering a table in mysql

I need to retrieve a report of the affected rows when a table has been altered with the following commands:
1.- Changing the engine:
ALTER TABLE <table> ENGINE=INNODB;
2.- Adding constraints:
ALTER TABLE nombre_tabla ADD PRIMARY KEY símbolo_clave_foránea;
ALTER TABLE nombre_tabla DROP PRIMARY KEY símbolo_clave_foránea;
ALTER TABLE nombre_tabla ADD FOREIGN KEY símbolo_clave_foránea;
ALTER TABLE nombre_tabla DROP FOREIGN KEY símbolo_clave_foránea;
3.- Adding a UNIQUE constraint.
Primary or Unique Key failure is look for duplicates, if you have nulls in there you'll need to sort them first.
E.g given MyTable(KeyField int not null) then
Select KeyField From MyTable
inner join (Select KeyField,Count() as NumberOfTimes Group By KeyField) Duplicates
Where NumberOfTimes > 1
Then you'll have to come up with something to do with them. Delete or rekey.
Foreign Keys just a outer join query with where key is null
e.g Given MyTable (KeyField int not null, ForeignKeyField int not null) and
MyLookUpTable(LookUpkey int not null, Description VarChar(32) not null) then
Select KeyField From MyTable
Left Join MyLookUpTable On MyTable.LookUpField = MyLookUpTable.LookUpKey
Where MyTable.LookUpField Is Null
Again you'll have to decide what to do with them. You could delete them, but this might help.
One way is to insert a "Missing" Record in the look Up Table, grab it's key, then do an update with join. So given that key is 999
Update m
Set LookUpField = 999
From MyTable m
Left Join MyLookUpTable On m.LookUpField = MyLookUpTable.LookUpKey
Where m.LookUpField Is Null
Now you can dig out 999s and deal with them at your leisure.

MySQL View where foreign key can be NULL

I would like to know how to create view which also works even if the foreign key is NULL. For example we have table Person which has a primary key and two foreign keys:
IdPerson
FkName
FkSurname
Both foreign keys can be NULL. Now we also have two tables, table Name:
IdName
Name
And table Surname:
IdSurname
Surname
Now we create view to display name and surname for each Person:
CREATE VIEW `Database`.`ViewPerson` AS
SELECT `N`.`Name`, `S`.`Surname`
FROM `Person` `P`, `Name` `N`, `Surname` `S`
WHERE (`P`.`FkName` = `N`.`IdName`) AND (`P`.`FkSurname` = `S`.`IdSurname`)
The problem is, if the foreign key FkSurname is NULL, than that row will not be displayed even though FkName is defined. I want that even if both foreign keys are NULL it still returns row where both columns are NULL. Now I know that I could solve it by adding in table Name and in table Surname row, that has NULL under Name/Surname and then in the FkName and FkSurname reference a row that has NULL values under those two columns. But I would still like to find out if there is a solution where foreign key is NULL and the row is returned.
If I understand your question correctly, you want to get the corresponding values (even if null) for the Name and Surname fields in the Name and Surname table for each record in the Person table.
This seems like a straightforward case where LEFT JOIN would work correctly. So, based on your query above, the SQL would be:
CREATE VIEW Database.ViewPerson AS
SELECT
N.Name, S.Surname
FROM Person P
LEFT JOIN Name N ON N.IdName = P.FkName
LEFT JOIN Surname S ON N.IdSurname = S.FkSurname;
(sorry of the syntax isn't 100% correct, I didn't go through and create a test table to confirm it)