Don't insert any combination of duplicates in SQL - mysql

Right now I just have
INSERT INTO MY_TABLE (VAL1, VAL2)
SELECT VAL1, VAL2 FROM OTHER_TABLE;
However, if MY_TABLE already has the values (1, 2), I don't want to let it insert (2,1) if (2,1) is in OTHER_TABLE;
Is there a way to do this here, or even while creating the tables?
I have tried to ALTER the table and create a UNIQUE constraint but it doesn't account for duplicates

Try this.
SELECT VAL1,
VAL2
FROM OTHER_TABLE a
WHERE NOT EXISTS (SELECT 1
FROM my_table b
WHERE ( a.val1 = b.val2
AND a.val2 = b.val1 )
OR ( a.val1 = b.val1
AND a.val2 = b.val2 ))

If there is already a UNIQUE constraint on the target table, you should be able to use the IGNORE command to prevent duplicate records.
http://dev.mysql.com/doc/refman/5.5/en/insert.html
INSERT IGNORE INTO MY_TABLE (VAL1, VAL2)
SELECT VAL1, VAL2 FROM OTHER_TABLE

We can place a condition while creating the table itself:
create table my_table
(
val1 int,
val2 int,
check( val,val2 not in (select val1,val2 from other_table,my_table where my_table.val1=other_table.val2 and my_table.val2=other_table.val1)
union
select val1,val2 from my_table mt1,mt2 where mt1.val1=mt2.val2 and mt1.val2=mt2.val1))
);

Related

Error nesting select statement into insert statement MYSQL [duplicate]

I'm trying to move old data from:
this_table >> this_table_archive
copying all columns over. I've tried this, but it doesn't work:
INSERT INTO this_table_archive (*) VALUES (SELECT * FROM this_table WHERE entry_date < '2011-01-01 00:00:00');
Note: the tables are identical and have id set as a primary key.
The correct syntax is described in the manual. Try this:
INSERT INTO this_table_archive (col1, col2, ..., coln)
SELECT col1, col2, ..., coln
FROM this_table
WHERE entry_date < '2011-01-01 00:00:00';
If the id columns is an auto-increment column and you already have some data in both tables then in some cases you may want to omit the id from the column list and generate new ids instead to avoid insert an id that already exists in the original table. If your target table is empty then this won't be an issue.
For the syntax, it looks like this (leave out the column list to implicitly mean "all")
INSERT INTO this_table_archive
SELECT *
FROM this_table
WHERE entry_date < '2011-01-01 00:00:00'
For avoiding primary key errors if you already have data in the archive table
INSERT INTO this_table_archive
SELECT t.*
FROM this_table t
LEFT JOIN this_table_archive a on a.id=t.id
WHERE t.entry_date < '2011-01-01 00:00:00'
AND a.id is null # does not yet exist in archive
Addition to Mark Byers answer :
Sometimes you also want to insert Hardcoded details else there may be Unique constraint fail etc. So use following in such situation where you override some values of the columns.
INSERT INTO matrimony_domain_details (domain, type, logo_path)
SELECT 'www.example.com', type, logo_path
FROM matrimony_domain_details
WHERE id = 367
Here domain value is added by me me in Hardcoded way to get rid from Unique constraint.
don't you need double () for the values bit? if not try this (although there must be a better way
insert into this_table_archive (id, field_1, field_2, field_3)
values
((select id from this_table where entry_date < '2001-01-01'),
((select field_1 from this_table where entry_date < '2001-01-01'),
((select field_2 from this_table where entry_date < '2001-01-01'),
((select field_3 from this_table where entry_date < '2001-01-01'));
More Examples & Detail
INSERT INTO vendors (
name,
phone,
addressLine1,
addressLine2,
city,
state,
postalCode,
country,
customer_id
)
SELECT
name,
phone,
addressLine1,
addressLine2,
city,
state ,
postalCode,
country,
customer_id
FROM
customers;

MYSQL - Upsert from one table to another

I am trying to use upsert to update and or insert from another table
INSERT INTO table1 (
`uniqueCol1`,
`uniqueCol2`,
`created`,
`dataCol`
)
VALUES (
1,
t1.uniqueCol2Value,
NOW(),
t1.dataColValue
)
ON DUPLICATE KEY UPDATE
`dataCol` = t1.dataColValue
Now from what I can tell I don't see how I can add what I think should be FROM table2 t1 into this to grab the values and put them into table1
I would suggest:
INSERT INTO table1 (
`uniqueCol1`,
`uniqueCol2`,
`created`,
`dataCol`
)
SELECT 1, uniqueCol2Value, NOW(), dataColValue FROM table2

Insert into table select where not exists affecting 0 rows

I'm trying to insert into a table with the following syntax:
INSERT INTO table1(
col1, col2, col3)
SELECT distinct
col1, col2, getDate()
FROM table2 WHERE NOT EXISTS(
SELECT 1 FROM table1, table2
WHERE ((table1.col1 = table2.col1) or (table1.col1 is null and table2.col1 is null))
AND ((table1.col2 = table2.col2) or (table1.col2 is null and table2.col2 is null)))
But when I run the query, it shows (0 row(s) affected).
The SELECT statement within the NOT EXISTS statement returns the correct number of rows that I don't want inserted. If I try to insert into the table without the WHERE NOT EXISTS statement, it inserts everything. I only want to insert rows that are not already in table1.
Try this:
INSERT INTO table1(col1, col2, col3)
SELECT distinct col1, col2, getDate()
FROM table2 WHERE NOT EXISTS(
SELECT 1 FROM table1
WHERE ((table1.col1 = table2.col1) or (table1.col1 is null and table2.col1 is null))
AND ((table1.col2 = table2.col2) or (table1.col2 is null and table2.col2 is null)))
You can optimize this query quite a bit, but as a quick fix you could change:
SELECT 1 FROM table1, table2
to:
SELECT 1 FROM table1
This will tie the outer table2 into your subquery.

How to insert conditionally

I create a temporary table #tbl(account, last_update). I have following two inserts from different source (could be tables from different databases) to insert account with last update date. For example
create table #tbl ([account] numeric(18, 0), [last_update] datetime)
insert into #tbl(account , last_update)
select table1.account, max(table1.last_update)
from table1 join…
group by table1.account
insert into #tbl(account , last_update)
select table2.account, max(table2.last_update)
from table2 join…
group by table2.account
The problem is this could cause duplicate account in the table #tbl. I either have to avoid it during each insert or remove the duplicate after both insert. Also, if there is account with two different last_update, I want the #tbl have the latest last_update. How do I achieve this conditional insert? Which one will have better performance?
Do you think you could rewrite your query to something like:
create table #tbl ([account] numeric(18, 0), [last_update] datetime)
insert into #tbl(account , last_update)
select theaccount, MAX(theupdate) from
(
select table1.account AS theaccount, table1.last_update AS theupdate
from table1 join…
UNION ALL
select table2.account AS theaccount, table2.last_update AS theupdate
from table2 join…
) AS tmp GROUP BY theaccount
The UNION ALL will build you 1 unique table combining table1 + table2 records. From there, you can act as if was a regular table, which means that you are able to find the max last_update for each record using a "group by"
insert into #tbl(account , last_update)
select account, last_update
from
(
select a.* from #table1 a where
last_update in( select top 1 last_update from #table1 b
where
a.account = b.account
order by last_update desc)
UNION
select a.* from #table2 a where
last_update in( select top 1 last_update from #table2 b
where
a.account = b.account
order by last_update desc)
) AS tmp

T-sql update only when matched with joined table 1 to 1

How can I efficiently update the table based on values from a join table
only when ID - identifier I use to join both of the tables matches perfectly
1 to 1. I mean when joined table has only one ID to the updated table?
DECLARE #T1 TABLE (
ID INT,
NAME VARCHAR(10),
Age int
)
INSERT INTO #T1 VALUES (1, 'Name', null)
DECLARE #T2 TABLE (
ID INT,
Age int
)
INSERT INTO #T2 VALUES (1, 28)
INSERT INTO #T2 VALUES (1, 29)
INSERT INTO #T2 VALUES (1, 30)
In this example table T2 has three records of the ID = 1 which corresponds to one ID
in T1.
And I would like to update T1 only when in T2 there is one record of ID = 1.
(I would like to avoid joining twice table t2 to solve this task ...)
Thanks!
;WITH T2
AS (SELECT ID,
MAX(Age) AS Age
FROM #T2
GROUP BY ID
HAVING COUNT(*) = 1)
UPDATE #T1
SET [#T1].Age = T2.Age
FROM #T1
JOIN T2
ON [#T1].ID = T2.ID