How to migrate a recursive table? - mysql

Let's say I have a table, category, which has 3 columns, id, parent_id and name.
I have several tables like this, and I want to consolidate them into one. At present, their IDs will clash (not unique across DBs) so I need to re-ID them. If I make id an auto_increment I can copy all the other columns over just fine, but then parent_id won't link up properly anymore. Is there some magical way I can get the parent_id to point to the correct new ID?
Looking for something like
INSERT INTO newtable (parent_id, name) SELECT ???, name FROM oldtable

How about
Generate a new table with a column containing the name of the old table and old id (oldid, oldtablename) along with a new ID
Add a new column 'newparentid'
Update each row's newparentid to be (SELECT newid FROM newtable nt WHERE oldtablename = row.oldtablename and nt.oldid = row.parent_id)

I imagine you could add an old_id column so that you'll still have the original id and you can run successive updates to the table to modify all the parent_ids to point to the new auto_inc ids. You would obviously have to kill any foreign keys requirements on the table first and reinstitute them after all the changes were made – Patrick

Related

How to insert into table a new row then do nothing if already exists(without UNIQUE key)

Let's say I have these two tables. Where I insert employees to employee table coming from the staging table.
staging table:
id
employee_id
name
1
12
Paul
2
13
Kyle
employee table
id
employee_id
name
5
4
Will
6
13
Kyle
Now, on the employee table let's say I'd like to copy what's on my staging table currently, using the INSERT SELECT INTO statement, Paul will be inserted but I don't want Kyle to be inserted since he's on the employee table already(employee.employee_id is the defining column).
I know this could be done by just setting a unique or primary key, on employee_id and just using the statement ON DUPLICATE KEY UPDATE then do nothing by just setting them back to their original values.
I'm new to SQL, and I'm stuck with the solution setting a UNIQUE key and ON DUPLICATE KEY UPDATE statement, but I'd like to know how to do this without that solution I mentioned?
First of all, you should keep in mind that the decision whether to create unique or primary keys or not does not depend on how to create insert statements or such. It's a matter of what your table should do and what not.
In order to achieve your goal, you can add a where to your insert statement which excludes the already existing entries, as example:
INSERT INTO employees (id, employee_id, name)
SELECT id, employee_id, name
FROM staging
WHERE employee_id NOT IN (SELECT employee_id FROM employees)
Break the problem down into its constituent parts
get a list of employees who are in the staging table but not in the target table
insert those records only
Part 1 can be achieved with a Left Join and Where condition that the target table is null. Wrap that up as a CTE and then use it in 2)

How to merge two db with same structure but different data

I'm working with phpmyadmin and I have to merge two db with same structure but different data.
The db have relation between tables (foreign key).
The data in two db may have same id, and so their foreign key.
I would like to know if it's possible merge the two db keeping all data, so, if a row already "exist", insert it with new id and update its foreign key.
thanks a lot
No easy way unfortunately. If you have TableA as a foreign key to TableB, you will need to
1) Insert data from source tableA to target tableA
2) create a (temp) table to store the mapping between source tableA ids and target tableA ids
3) Use this mapping table when inserting data from tableB to convert the tableA ids to the new ones in the target db
... and so on. It can get quite hairy if you have a deep hierarchy of tables, but hopefully you get the idea. Take backups before you start.
Another idea that you might want to consider is using a cursor:
Assume table A is the one that you want to keep and table B is the one you want to remove.
Declare a cursor for table B and select all the records.
Loop each record selected from the cursor and check.
Case 1: If the ID is exists on table A, insert the record to table A with same details.
Case 2: If the ID is exists on table B, insert the record and modify the ID and foreign key.
Once all the records have been checked, drop table B.
Sorry, I just can give an idea at the moment.

auto_increment index depends other table

I have two tables:
Friends :
id name
1 jhon
2 peter
Teammates:
id name
3 juan
i am looking for a way two auto increment the id of the second table (teammates) according to the first table ( Friends ).
When I add a new register to Teammates it never match with an id of Friends
I think this is not good practice. If you do so, you are introducing an implicit functional dependency between both tables outside of the declared design. If you want to it anyway, you can use a trigger to asign the value instead of making the column autoincrement.
I would suggest to have a table for all people with the real autoincrement id, then you can use several approaches:
i) Make your two actual tables take id values as foreign keys of this new table, with the corresponding integrity constraint.
ii) Simply create 2 views of the table: One for friends, other for teammates.
Table_Friends: (id, name, role)
View_Friends: Select id, name from table_Friends where role = value_for_friend_role
View_Mates: Select id, name from table_Friends where role = value_for_teammate_role

How Do I delete these orphan records from my Table, Iteratively?

I have 2 tables like this
words(word_id, value);
word_map(sno(auto_inc), wm_id, service_id, word_id, base_id, root_id);
in which sno is auto incremented just for indexing.
wm_id is the actual id which are unique for each service like
(serviceid, wm_id together form a unique key).
base_id and root_id are referenced to wm_id i.e., I store the values of respective wm_id of new word being inserted.
My Requirement now is I want to delete the records from this table where, a words's base_id or root_id does not exists in the table
For example,
A new word with tr_id = 4, its base_id = 2 and root_id = 1 then There must two other records with tr_id s 2 and 1 if not we can call it as an orphan and that record with wm_id = 4 must be deleted, then records with other wm_ids having this 4 as base_id or root_id must also be deleted as they r also now orphans if 4 gets deleted and so on.
Can anybody suggest me the solution for the problem.
What I tried:
I tried write a procedure using while in which it has a query like,
delete from words_map where base_id not in (select wm_id from words_map) or root_id not in (select wm_id from words_map)
But deleting/ or updating on same table using this kind of nested queries is not possible, So I am searching for an alternate way.
What I doubt is :
I thought of reading these wm_ids into an array then reading one by one deleting based on that, but I dont think we have arrays in stored
procedures.
Is Cursor an alternative for this sitution.
or any other best solution for this problem.
EDIT 1: Please go through this http://sqlfiddle.com/#!2/a4b6f/15 for clear experimental data
Any and early help would be appreciated

mysql group by set id

MYSQL Database:
I have a table of data that I need to put into two tables.The one table contains persons and an animal. Every record is a person and an animal. I am chaning this to a multi table database and want to group by the persons name, and then give the group an id (like a customer id) and then in my other table pass the customer ID to the idcustomer to join the two tables. To simplfy this i dont mind if these newly created ids are in the single table with new column names. I can after the fact export them out and import them.
The question really is, how can I create a group by customer name, give that customer and ID and then use that same id in a column to do the join.
To describe the scheme:
I have taken over a project. The database as of now is one table. In this one table is:
persons name, address, childsname, description of child
What would like it to be at least to start with is:
id_person, person name, childsname, childparent, description of child.
The id of the person and the childsparent should be the same. When I break the table down, and put the child information in the child table, the child will have a parent id.
I still plan on having two tables. But I can export and create the tables, my problem is assiging the parent id to the child column with the current data.
An example of a couple rows would be:
person_name, address, childsname, description
mark twain, 23 st., Buckweat, short smart kid
mark twain, 23 st., Daniel, short kinda smart
Instead i would like to have 2 tables, one for the parents and the other table is their children.
The way this database was setup, if one person has more than one child, there is another row that lists all of the same information.
What I have planned is to have multiple tables with a join.
The original database has no index, or unique identifier.
What I want to do is loop through the records, since there is no unique id, if the customer name is identical, meaning they are listed twice, then they must have more than one child.
In that case, i want to be able to go through the database and assign a id for the parents. and also ad another colum called parentid, which will be the child table.
To create the table you need you can use a temporary table - to which you will insert all parent names and give them IDs. Then you can update the existing table:
CREATE TABLE name_to_id (
`id` INT(11) AUTO_INCREMENT,
`name` VARCHAR(256),
PRIMARY KEY (`id`));
INSERT INTO name_to_id (name)
SELECT DISTINCT name FROM my_table;
ALTER TABLE my_table
ADD COLUMN id INT(11) FIRST,
ADD COLUMN parent_id INT(11) AFTER childsname;
UPDATE my_table t
JOIN name_to_id n ON t.name = n.name
SET t.id = n.id, t.parent_id = n.id;
To create the parents and children separate tables you can use:
CREATE TABLE parents AS
SELECT id, name, address FROM my_table
GROUP BY id;
CREATE TABLE children AS
SELECT childsname, parent_id, description
FROM my_table;
You would probably want to ALTER those tables later to add a primary keys and other needed indexes.