SQL SELECT INSERT INTO Generate Unique Id - sql

I'm attempting to select a table of data and insert this data into another file with similar column names (it's essentially duplicate data). Current syntax as follows:
INSERT INTO TABLE1 (id, id2, col1, col2)
SELECT similiarId, similiarId2, similiarCol1, similiarCol2
FROM TABLE2
The problem I have is generating unique key fields (declared as integers) for the newly inserted records. I can't use table2's key's as table1 has existing data and will error on duplicate key values.
I cannot change the table schema and these are custom id columns not generated automatically by the DB.

Does table1 have an auto-increment on its id field? If so, can you lose similiarId from the insert and let the auto-increment take care of unique keys?
INSERT INTO TABLE1 (id2, col1, col2) SELECT similiarId2, similiarCol1, similiarCol2
FROM TABLE2

As per you requirement you need to do you query like this:
INSERT INTO TABLE1 (id, id2, col1, col2)
SELECT (ROW_NUMBER( ) OVER ( ORDER BY ID ASC ))
+ (SELECT MAX(id) FROM TABLE1) AS similiarId
, similiarId2, similiarCol1, similiarCol2
FROM TABLE2
What have I done here:
Added ROW_NUMBER() which will start from 1 so also added MAX() function for ID of destination table.
For better explanation See this SQLFiddle.

Im not sure if I understad you correctly:
You want to copy all data from TABLE2 but be sure that TABLE2.similiarId is not alredy in TABLE1.id, maybe this is solution for your problem:
DECLARE #idmax INT
SELECT #idmax = MAX(id) FROM TABLE1
INSERT INTO TABLE1 (id, id2, col1, col2)
SELECT similiarId + #idmax, similiarId2, similiarCol1, similiarCol2
FROM TABLE2
Now insert will not fail because of primary key violation because every inserted id will be greater then id witch was alredy there.

If the id field is defined as auto-id and you leave it out of the insert statement, then sql will generate unique id's from the available pool.

In SQL Server we have the function ROW_NUMBER, and if I have understood you correctly the following code will do what you need:
INSERT INTO TABLE1 (id, id2, col1, col2)
SELECT (ROW_NUMBER( ) OVER ( ORDER BY similiarId2 ASC )) + 6 AS similiarId,
similiarId2, similiarCol1, similiarCol2
FROM TABLE2
ROW_NUMBER will bring the number of each row, and you can add a "magic value" to it to make those values different from the current max ID of TABLE1. Let's say your current max ID is 6, then adding 6 to each result of ROW_NUMBER will give you 7, 8, 9, and so on. This way you won't have the same values for the TABLE1's primary key.
I have asked Google and it said to me that Sybase has the function ROW_NUMBER too (http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.sqlanywhere.12.0.1/dbusage/ug-olap-s-51258147.html), so I think you can try it.

If you want to make an identical table why not simply use (quick and dirty) Select INTO method ?
SELECT * INTO TABLE2
FROM TABLE1
Hope This helps.

Make the table1 ID IDENTITY if it is not a custom id.
or
Create new primary key in table1 and make it IDENTITY, and you can keep the previous IDs in the same format (but not primary key).

Your best bet may be to add an additional column on Table2 for Table1.Id. This way you keep both sets of Keys.
(If you are busy with a data merge, retaining Table1.Id may be important for any foreign keys which may still reference Table1.Id - you will then need to 'fix up' foreign keys in tables referencing Table1.Id, which now need to reference the applicable key in table 2).

If you need your 2nd table keep similar values as in 1st table , then donot apply auto increment on 2nd table.

If you have large range, and want easy fast make and don't care about ID:
Example wit CONCAT
INSERT INTO session(SELECT CONCAT("3000", id) as id, cookieid FROM `session2`)
but you can using also REPLACE

Related

Clone a record, then use its auto increment id for further operations

Update:
After narrowing down the code it seems that the line
INSERT INTO table1 TABLE table1_temp RETURNING id
is causing the issue. Any tips what is wrong with this?
Original question:
table1 has many colums (I don't care which) and it has an auto increment primary key (id). This is what I need to do and how I'm trying:
First, I'd like to duplicate a record in table1.
BEGIN;
CREATE TEMP TABLE table1_temp ON COMMIT DROP AS
SELECT * FROM table1 WHERE id = <some integer>;
ALTER TABLE table1_temp DROP COLUMN id;
WITH generated_id AS (
INSERT INTO table1 TABLE table1_temp RETURNING id
)
Then, perform an insert to some_table where I need to use the generated id of the copy that was created in table1.
INSERT INTO some_table (something, the_id_into_this)
VALUES ('some value', (SELECT id FROM generated_id));
Then get some data from yet_another_table (columns: somestuff, id_here) and use this and the id for an insert into that same table.
INSERT INTO yet_another_table
(SELECT somestuff,
(SELECT id FROM generated_id) AS id_here
FROM yet_another_table
WHERE id_here = <some integer>)
Finally, I need to return the id so I can use it in my app...
RETURNING id_here AS id;
COMMIT;
Am I on the right path implementing this? When running the query, I get the following error:
column "id" is of type integer but expression is of type character
varying HINT: You will need to rewrite or cast the expression.
It doesn't tell me the line number where it occurrs and I have no idea what might cause this.
INSERT INTO table1 TABLE table1_temp
You cannot do that because table1_temp has different set of columns (you dropped id column).
You need to specify columns explicitly (all but id column):
INSERT INTO table1(col1, col2, ...) TABLE table1_temp
I found a simple solution for cloning a record with an auto increment id that doesn't require you to specify any other columns of the table:
BEGIN;
CREATE TEMP TABLE table1_temp ON COMMIT DROP AS
SELECT * FROM table1 WHERE id = #;
UPDATE table1_temp SET id = nextval('table1_seq');
INSERT INTO table1 TABLE table1_temp;
COMMIT;
And for the CTE part of the question, here is how you can reuse a returned value at multiple subsequent queries by concatenating WITH statements:
WITH generated_id AS (
INSERT INTO ... RETURNING id
), _ AS (
QUERY1 ... SELECT id FROM generated_id ...
), __ AS (
QUERY2 ... SELECT id FROM generated_id ...
...

Use inserted value as a parameter for other inserts

There is a db2 database with two tables. The first one, table1, has autoincrement column ID. It is the foreign key for the table2.
A am writing an HTML generator for SQL queries. So with some input parameters it generates a query or multiple queries. It is not connected to the database.
What I need is to get that autoincrement field and use it in next queries.
So basically, the scenario is:
insert into table1;
select autogenerated field ID;
insert into table2 using that ID;
insert into table2 using that ID;
...some more similar inserts...
insert into table2 using that ID;
And all that SQL query should be generated and then used as a single SQL script.
I was thinking about something like this:
SELECT ID FROM FINAL TABLE (INSERT INTO Table1 (t1column1, t1column2, etc.)
VALUES (t1value1, t1value2, etc.))
But I don't know, how I can write the result into a variable so I could use it in next queries like this:
INSERT INTO Table2 (foreignKeyCol, t2column1, t2column2, etc.)
VALUES ($ID, t2value1, t2value2, etc.)
I could just paste that select instead of $ID, but the second query can be used several times with the same $ID and different values.
EDIT: DB2 10.5 on Linux.
You can chain several inserts together using CTEs, like so:
WITH idcte (id) as (
SELECT ID FROM FINAL TABLE (
INSERT INTO Table1 (t1column1, t1column2, etc.)
VALUES (t1value1, t1value2, etc.)
)
),
ins1 (id) as (
SELECT foreignKeyCol FROM FINAL TABLE (
INSERT INTO Table2 (foreignKeyCol, t2column1, t2column2, etc.)
SELECT id, t2value1, t2value2, etc.
FROM idcte
)
),
-- more CTEs
SELECT foreignKeyCol FROM FINAL TABLE (
-- your last INSERT ... SELECT FROM
)
Essentially you will have to wrap each INSERT into a SELECT FROM FINAL TABLE for this to work.
Alternatively, you can use a global variable to keep the ID value:
CREATE VARIABLE myNewId INT;
SET myNewId = (SELECT ID FROM FINAL TABLE (
INSERT INTO Table1 (t1column1, t1column2, etc.)
VALUES (t1value1, t1value2, etc.)
));
INSERT INTO Table2 (foreignKeyCol, t2column1, t2column2, etc.)
VALUES (myNewId, t2value1, t2value2, etc.);
DROP VARIABLE myNewId;
This assumes a recent version of Db2 for LUW.

Delete subset of a table based on temp table

I have a table, say myTable. I also have a temp table, say myTableTemp, that contains the exact values I want to keep eliminate from myTable (myTable has more value than I need).
I was initially thinking I could drop myTable, and then rename myTableTemp to myTable`. However there are many FK contraints that I do not want to touch. In theory, my query would look like:
DELETE FROM myTable where in (myTableTemp);
At least logically that is how i think about it
EDIT: The temp table contains the data I want to DELETE from myTable
DELETE FROM myTable where in (myTableTemp);
Isn't the above backwards? Don't you want to keep all the values in myTableTemp?
I would do the following:
DELETE FROM myTable t1
WHERE NOT EXISTS ( SELECT 1 FROM myTableTemp t2
WHERE t2.primary_key = t1.primary_key );
Again, that's assuming that you want to keep everything in myTableTemp and delete everything in myTable that isn't in myTableTemp.
As an alternate solution to eliminate from myTable items present in myTableTemp:
DELETE FROM myTable
WHERE primary_key IN ( SELECT primary_key FROM myTableTemp )
;
It is usually believed that [NOT] EXISTS queries perform better than those using [NOT] IN. But it is not always that obvious.

How to insert row for each unique value found in column

How could I, in SQL Server 2008, write a SQL statement that would insert one row for each distinct value it finds in one column in the same table?
Edit:
The table I want to add rows to the same table I'm checking.
I have normalized table with a column [Name], and [Hobby], so how do I insert one new hobby for each name?
Input greatly appreciated =]
try
INSERT INTO TargetTable (SomeColumn)
SELECT DISTINCT TheSourceColumn From SomeSourceTable;
IF that is not what you are looking for please provide more details like what the data model looks like etc.
UPDATE - after edit from OP:
I am not sure that you data model is good but you can do this:
INSERT INTO TheTable (NAME, HOBBY)
SELECT DISTINCT X.NAME, #SomeHOBBY FROM TheTable X;
You could use something like
Insert into table1
Select distinct col1 from tabl2
The above should work as long as table1 has just one column of the same data type as col1 of tabl2

How can I merge two MySQL tables?

How can I merge two MySQL tables that have the same structure?
The primary keys of the two tables will clash, so I have take that into account.
You can also try:
INSERT IGNORE
INTO table_1
SELECT *
FROM table_2
;
which allows those rows in table_1 to supersede those in table_2 that have a matching primary key, while still inserting rows with new primary keys.
Alternatively,
REPLACE
INTO table_1
SELECT *
FROM table_2
;
will update those rows already in table_1 with the corresponding row from table_2, while inserting rows with new primary keys.
It depends on the semantic of the primary key. If it's just autoincrement, then use something like:
insert into table1 (all columns except pk)
select all_columns_except_pk
from table2;
If PK means something, you need to find a way to determine which record should have priority. You could create a select query to find duplicates first (see answer by cpitis). Then eliminate the ones you don't want to keep and use the above insert to add records that remain.
INSERT
INTO first_table f
SELECT *
FROM second_table s
ON DUPLICATE KEY
UPDATE
s.column1 = DO_WHAT_EVER_MUST_BE_DONE_ON_KEY_CLASH(f.column1)
If you need to do it manually, one time:
First, merge in a temporary table, with something like:
create table MERGED as select * from table 1 UNION select * from table 2
Then, identify the primary key constraints with something like
SELECT COUNT(*), PK from MERGED GROUP BY PK HAVING COUNT(*) > 1
Where PK is the primary key field...
Solve the duplicates.
Rename the table.
[edited - removed brackets in the UNION query, which was causing the error in the comment below]
Not as complicated as it sounds....
Just leave the duplicate primary key out of your query....
this works for me !
INSERT INTO
Content(
`status`,
content_category,
content_type,
content_id,
user_id,
title,
description,
content_file,
content_url,
tags,
create_date,
edit_date,
runs
)
SELECT `status`,
content_category,
content_type,
content_id,
user_id,
title,
description,
content_file,
content_url,
tags,
create_date,
edit_date,
runs
FROM
Content_Images
You could write a script to update the FK's for you.. check out this blog: http://multunus.com/2011/03/how-to-easily-merge-two-identical-mysql-databases/
They have a clever script to use the information_schema tables to get the "id" columns:
SET #db:='id_new';
select #max_id:=max(AUTO_INCREMENT) from information_schema.tables;
select concat('update ',table_name,' set ', column_name,' = ',column_name,'+',#max_id,' ; ') from information_schema.columns where table_schema=#db and column_name like '%id' into outfile 'update_ids.sql';
use id_new
source update_ids.sql;