I have a table T1 with some fields like
id,key_id ,name,date etc..
id is a auto incrementing field
key_id is a value obtained from id like prefix/id
Prefix is constant for all the rows and just id changes which is the id for the corresponding row..
It looks like something like this
$sql = " ALTER TABLE T1 AUTO_INCREMENT = 1234567890,
ADD id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT ";
UPDATE T1
SET key_id = CONCAT('12.345','/',id)
Now due to some reasons i want to create a new table T2 which would be the parent of T1 and id would be the primary key T2 and Key_id would become primary key of T1. T2 should also include other two fields like key_id and name..
ok the main reason for parent table is : i might create another table T3 which will also have id and id should have different values for T1 and T3 so i want to maintain a master table which has id as a primary key and other child tables will fetch the ids only from master table..
How can I do this?
Why would you want to store a redundant data in another column "key_id"?
Since the prefix is constant, the id is enough. Perform the concatenation in your code.
Also, that way, you can have id as primary key for both tables and get the key_id by prefixing the "Prefix".
Related
I'm relatively new to relational databases and I'm not sure if what I want to do is possible. Could some one please tell me how to do this.
I have this named table1 where id is primary key
Id userName
1 A
2 C
3 F
and I have this table2 which is now empty, Id is a foreign key that REFERENCEd on table1 (Id)
Id amount
I want to set up my database so that the values in table1 id column are equal to the the values in tables2 id column and anytime an entry is added in table1 id column ,the same value is added table2 id column .
That change will also be reflected in table_1
I'm upgrading a DB schema. A table is divided into 2 tables. These two tables are linked and the only way to link them is using a varchar name field in the original table.
Problem is that customer could have duplicate names, since name is not the Primary/Unique Key.
I came here looking for ideas to make these names unique so it can be used as a key when moving the data to the two new linked tables.
As I'm writing this, I had the idea of CONCATing the current PK to name (as in CONCAT(name,id) as newName) and use this as key.
There's also a unique code field, but this only goes into one of the new tables.
Example Schema:
tableA
a_id INT(11) PRI AUTO_INCREMENT
code VARCHAR(10) UNIQUE
name VARCHAR(30) NOT NULL
newTableB
b_id INT(11) PRI AUTO_INCREMENT
name VARCHAR(30)
newTableC
c_id INT(11) PRI AUTO_INCREMENT
b_id INT(11) FK->newTableB
code VARCHAR(10) UNIQUE
What I want:
Generate New b_id's (auto_increment)
newTableB.name imported from tableA.name
newTableC.code imported from tableA.code
newTableC.c_id imported from tableA.a_id
a_id is an FK in another fourth table that's staying the same. After the changes above, c_id will now be valid FK in this fourth table.
My Challenge:
How Do insert into these new tables but still keep the original name<->code<->a_id relationship and transfer tableA.a_id values to newTableC.c_id. Don't care if b_id gets new auto_incr. values.
Not sure how clear I'm making problem come across, but feel free to ask any questions.
Thanks
Dan
I've usually done a task like this in several parts. First insert to table b but put the id field from a in the name column instead of the name. Then insert the data into tablec from table a. Then update tableb name field by joining to table a on the a.id and b.name fields. BUt im not sure if you can use a join in an update in mysql. Should bea way to write the statement though once you have the data there.
Alternatively, I temporarily add a column to table b called tableid. Then I put the data in tableb including the a id and use that to join to table a to get the b.id and table A data for table c. When it is done, I drop the tableA column from table b.
how about this
CREATE TABLE temp_newTableB AS (SELECT * FROM newTableB);
DELETE FROM newTableB WHERE b_id NOT IN (SELECT b_id FROM temp_newTableB GROUP BY name);
DROP TABLE temp_newTableB ;
but is there any rule on which you are going to decide which b_id you want to keep in the newTableC as some of the duplicate named b_id will be removed from newTableB by the above query??
How can I insert values into a table (MySQL) in the following manner:
On all the rows of a table, in order of ID column (PK), insert incrementing number in column 'num'?
For example if the table had 3 rows , with Ids 1,5,2, I want ID 1 to get num=1, ID 2 to get num=2 and ID 5 to get num=3.
EDIT
I will explain why I (think I) need this:
I am trying to split a column off a table into a separate table with a 1-to-1 relation. I thought I would get all the values in order of ID and insert them into the new table, with an auto-incrementing PK. then I know that, in order of ID, the values for the new reference column in the original table will be auto-incrementing numbers. So I want to insert them in that order. I hope this is clear.
i am currently not in front of sql database engine and cannot therefore submit fully verified sql code. however if your num field is not an autoincrement field than do something like this:
CREATE TEMPORARY TABLE temp_table_x (
num int auto_increment primary key,
reference_id int
);
INSERT temp_table_x (reference_id)
SELECT id FROM source_table ORDER BY id;
UPDATE source_table st
SET st.num = x.num
FROM temp_table_x x
WHERE reference_id = id;
As long as the num field is an autoincrement field it should be as simple as:
INSERT INTO
yourTable (
field1,
field2,
field3,
etc
)
SELECT
field1,
field2,
field3
FROM
yourSourceTable
ORDER BY
originalIdField
I would NOT make a field that references a column in another table an auto-increment column.
Even if the column that it references is an auto-increment, I wouldn't make the column auto-increment. It will be difficult to keep the columns in sync. If an insert is rolled back in one table but not the other, you'll be out of sync until you reset the auto_increment value.
If it's a 1 to 1 relationship, feel free to make the column a primary key. That way it will be ordered by the column, and it will ensure unique values. However, if any two columns must match, they should not both be auto-increment, though, they should be of the same type (eg. INTEGER).
For example, here's our original table, where the first column is an auto-increment integer column:
id customer_name email_address
---------------------------
1 jsmith jsmith#aol.com
2 bwilliams bwilliams#aol.com
If you wanted to split the email_address off to its own table, in a 1 to 1 relationship:
id email_address
---------------------------
1 jsmith#aol.com
2 bwilliams#aol.com
I would make the first column an integer field and make it the primary key, but it would NOT be an auto-increment column.
To insert values into such a table, you could simply do this:
INSERT INTO table2
(id, email_address)
SELECT id, email_address
FROM table1
ORDER BY id
I found the answer. It is very simple:
SET #c=0;
UPDATE myTable SET num = (#c:=#c+1) ORDER BY id
For the sake of simplicity lets say I have a table with 3 columns; id, parent_id and name. In this table id is my auto-incrementing primary key. I want to group multiple names together in this table, to do this all names in a group will share the same parent_id. If I am inserting the first name in the group I want the id=parent_id, if i am inserting another name I want to specify a specific parent_id to place that name into a specific group. It would be nice if I could define a default for that column to be the same as the id, if I specify a value for parent_id in the insert query then I would like it to use that value. I know you can set a default to be a specific static value, but can you specify the default to be the same as that row's auto-incrementing primary key? Perhaps this is a job for a trigger or stored procedure?
(I know I could obtain the primary key generated by the last insert and then update the table, but that's 2 quires I'd rather not burn.)
Thanks!
This is a job of a trigger!
CREATE TRIGGER NAME1 AFTER INSERT ON TABLE1
BEGIN
UPDATE TABLE1 SET parent_id = id WHERE (parent_id IS NULL OR parent_id = '');
END;
INSERT INTO TABLE1 (id,parent_id) VALUES (null,null); -- parent_id will be equal to id
INSERT INTO TABLE1 (id,parent_id) VALUES (null,'1'); -- parent_id will be 1
INSERT INTO TABLE1 (id,parent_id) VALUES (null,'2'); -- parent_id will be 2
I want to know if I can repopulate the autoincrement value in mysql.
Because, I have records that look similar:
ID Name
1 POP
3 OLO
12 lku
Basically , I want a way to update the ID to this
ID Name
1 POP
2 OLO
3 lku
Is there any way to do this in mysql?
Thanks.
It's not best practice to fiddle your primary keys - better to let your DB handle it itself. There can be issues if, in between the UPDATE and ALTER, another record is added. Because of this, you must LOCK the table, which might hang other queries and spike load on a busy production server.
LOCK TABLES table WRITE
UPDATE table SET id=3 WHERE id=12;
ALTER TABLE table AUTO_INCREMENT=4;
UNLOCK TABLES
OR - for thousands of rows (with no foriegn key dependencies):
CREATE TEMPORARY TABLE nameTemp( name varchar(128) not null )
INSERT INTO name SELECT name FROM firstTable
TRUNCATE firstTable
INSERT INTO firstTable SELECT name FROM nameTemp
The latter method will only work where you have no foreign keys. If you do, you'll require a lookup table.
CREATE TEMPORARY TABLE lookup( newId INTEGER AUTO_INCREMENT, oldId INTEGER, PRIMARY KEY newId( newId ) );
INSERT INTO lookup (oldId) SELECT id FROM firstTable
[do temp table queries above]
You now have a lookup table with the old to new ids which you can use to update the foreign key dependencies on your other tables (on a test server!)
Changing the primary key is a very bad idea as it endangers your referential integrity (what if another table uses the id without having a foreign key with proper "on change"?).
If you really, really have to do it and don't care about bad side-effects:
Create a second table with identical structure
INSERT INTO new_table (id, [other fields]) SELECT NULL, [other fields] FROM old_table;
DROP old_table;
RENAME new_table old_table;
Warning:
This will damage every other table that has foreign keys on this table (but if you had such then you wouldn't be doing this anyways).
You may want to try something like...
Create Temporary table MyBackup
( ID as your autoincrement,
OldID as Int for backlinking/retention,
RestOfFields as their type )
insert into MyBackup
( OldID
RestOfFields )
select
ID as OldID,
RestOfFields
from
YourOriginalTable
order by
ID (this is your original ID)
Then you'll have a new table with an autoincrement with new IDs assigned, yet have a full copy of their original ID. Then, you can do correlated updates against other tables and set the ID = ID where ID = OldID. By keeping your insert via order by the original ID, it will keep the numbers from replacing out of sequence.. Ex: if your table was orderd as
Old ID = 3, new ID = 1
Old ID = 1, new ID = 3
Old ID = 12, new ID = 2
Your old 3's will become 1's, then the 1's would become 3's, and 12's become 2's
Old ID = 1, new ID = 1
Old ID = 3, new ID = 2
Old ID = 12, new ID = 3
your 3's won't overwrite the higher number, and the 12's won't conflict with the 3's since the threes were already lowered to 2's.