multiple insert row if not exists (based on multiple columns) - mysql

Imagine an existing table with data (names are self explanatory):
id,name,telephone_1,telephone_2
i want to insert multiple new records with one INSERT (hopefully multiple new records with one insert -if thats a problem i could fall back to insert one-by-one), but i want a new row to be added ONLY if the telephone_1 OR the telephone_2 of the new record does NOT already exist either in telephone_1 OR the telehpone_2 of an existing record.
That means if we have existing data
1, Jimmy, 123, 456
i should not be able to add a
NULL,John,444,123
because John's telephone_2 exists already as telephone_1 of Jimmy.
I'm planning to let mysql do the heavy work instead of my program, but how can i do that? I have done something similar in the past using UNIQUE indexes, but the problem in this case is that the columns are 2. The telephone_1 should not collide with telephone_1 and also should not collide with telephone_2 (and same for telephone_2)
UPDATE-CLARIFICATION: The data i'm trying to insert are not from another table; they are generated on the fly from my program.

Suppose your table name is contacts, then try to insert record:
INSERT INTO contacts(name,telephone_1,telephone_2)
SELECT 'John', 444, 123
FROM contacts
WHERE telephone_1 NOT IN (444, 123)
AND telephone_2 NOT IN (444, 123)
LIMIT 1;
Trick there: if WHERE condition is false then SELECT returns no rows and record is not inserted.
Try here: http://sqlfiddle.com/#!2/5a6e0/1

Try this:
Insert into tableA select * from tableB where tableB.telephone_1 not in (select telephone_1 tableA union select telephone_2 tableA ) AND tableB.telephone_2 not in (select telephone_1 tableA union select telephone_2 tableA )
where
tableA is your main table where you want to insert new record.
tableB is other table from where you want to fetch record

Related

How to merge 2 tables in mySQL [duplicate]

I'm trying to write a query that extracts and transforms data from a table and then insert those data into another table. Yes, this is a data warehousing query and I'm doing it in MS Access. So basically I want some query like this:
INSERT INTO Table2(LongIntColumn2, CurrencyColumn2) VALUES
(SELECT LongIntColumn1, Avg(CurrencyColumn) as CurrencyColumn1 FROM Table1 GROUP BY LongIntColumn1);
I tried but get a syntax error message.
What would you do if you want to do this?
No "VALUES", no parenthesis:
INSERT INTO Table2(LongIntColumn2, CurrencyColumn2)
SELECT LongIntColumn1, Avg(CurrencyColumn) as CurrencyColumn1 FROM Table1 GROUP BY LongIntColumn1;
You have two syntax options:
Option 1
CREATE TABLE Table1 (
id int identity(1, 1) not null,
LongIntColumn1 int,
CurrencyColumn money
)
CREATE TABLE Table2 (
id int identity(1, 1) not null,
LongIntColumn2 int,
CurrencyColumn2 money
)
INSERT INTO Table1 VALUES(12, 12.00)
INSERT INTO Table1 VALUES(11, 13.00)
INSERT INTO Table2
SELECT LongIntColumn1, Avg(CurrencyColumn) as CurrencyColumn1 FROM Table1 GROUP BY LongIntColumn1
Option 2
CREATE TABLE Table1 (
id int identity(1, 1) not null,
LongIntColumn1 int,
CurrencyColumn money
)
INSERT INTO Table1 VALUES(12, 12.00)
INSERT INTO Table1 VALUES(11, 13.00)
SELECT LongIntColumn1, Avg(CurrencyColumn) as CurrencyColumn1
INTO Table2
FROM Table1
GROUP BY LongIntColumn1
Bear in mind that Option 2 will create a table with only the columns on the projection (those on the SELECT).
Remove both VALUES and the parenthesis.
INSERT INTO Table2 (LongIntColumn2, CurrencyColumn2)
SELECT LongIntColumn1, Avg(CurrencyColumn) FROM Table1 GROUP BY LongIntColumn1
I believe your problem in this instance is the "values" keyword. You use the "values" keyword when you are inserting only one row of data. For inserting the results of a select, you don't need it.
Also, you really don't need the parentheses around the select statement.
From msdn:
Multiple-record append query:
INSERT INTO target [(field1[, field2[, …]])] [IN externaldatabase]
SELECT [source.]field1[, field2[, …]
FROM tableexpression
Single-record append query:
INSERT INTO target [(field1[, field2[, …]])]
VALUES (value1[, value2[, …])
Remove VALUES from your SQL.
Remove "values" when you're appending a group of rows, and remove the extra parentheses. You can avoid the circular reference by using an alias for avg(CurrencyColumn) (as you did in your example) or by not using an alias at all.
If the column names are the same in both tables, your query would be like this:
INSERT INTO Table2 (LongIntColumn, Junk)
SELECT LongIntColumn, avg(CurrencyColumn) as CurrencyColumn1
FROM Table1
GROUP BY LongIntColumn;
And it would work without an alias:
INSERT INTO Table2 (LongIntColumn, Junk)
SELECT LongIntColumn, avg(CurrencyColumn)
FROM Table1
GROUP BY LongIntColumn;
Well I think the best way would be (will be?) to define 2 recordsets and use them as an intermediate between the 2 tables.
Open both recordsets
Extract the data from the first table (SELECT blablabla)
Update 2nd recordset with data available in the first recordset (either by adding new records or updating existing records
Close both recordsets
This method is particularly interesting if you plan to update tables from different databases (ie each recordset can have its own connection ...)
inserting data form one table to another table in different DATABASE
insert into DocTypeGroup
Select DocGrp_Id,DocGrp_SubId,DocGrp_GroupName,DocGrp_PM,DocGrp_DocType
from Opendatasource( 'SQLOLEDB','Data Source=10.132.20.19;UserID=sa;Password=gchaturthi').dbIPFMCI.dbo.DocTypeGroup
Do you want to insert extraction in an existing table?
If it does not matter then you can try the below query:
SELECT LongIntColumn1, Avg(CurrencyColumn) as CurrencyColumn1 INTO T1 FROM Table1
GROUP BY LongIntColumn1);
It will create a new table -> T1 with the extracted information

MySQL Trigger duplicate data

i had query like this
CREATE TRIGGER `tambah_riwayatobat` AFTER INSERT ON `obat`
FOR EACH ROW insert into riwayat_obat(nama, keterangan, distributor,tanggal)
(select new.nama, 'Masuk', d.nama ,now()
From distributor d
join obat ON new.id_distributor = d.id_distributor)
i try to insert data with trigger and one of part data i fetch with constraint, but why the data be duplicate entry ?
Output :
example, if i try to insert data obat 1st time, data on tambah_riwayatobat insert 1 too
if i try to insert data obat 2nd time, data on tambah_riwayatobat insert 2 times with same data
if i try to insert data obat 3rd time, data on tambah_riwayatobat insert 3 times with same data
I'm not certain exactly what's happening, but it's a result of the join in your trigger code. You’re joining obat to distributor, but your join condition makes no mention of obat so you're getting some sort of cross-product where on the second and subsequent INSERT your SELECT subquery is selecting more than one row.
You shouldn't (and don't need to) use the join, since all the data you need from obat is already in the pseudorecord NEW. The following code should work much better:
CREATE TRIGGER `tambah_riwayatobat`
AFTER INSERT ON `obat`
FOR EACH ROW
INSERT INTO riwayat_obat
(nama, keterangan, distributor, tanggal)
(SELECT NEW.nama, 'Masuk', d.nama, now()
FROM distributor d
WHERE new.id_distributor = d.id_distributor
LIMIT 1);
The LIMIT clause will ensure that the SELECT selects only one row, so the INSERT inserts only one row; if distributor.id_distributor is a primary key the LIMIT clause is unnecessary.

How do I combine multiple conditions (exists and not exists) checks before inserting a new record in mysql?

I would like to build a query to insert a new record, after checking with an EXISTS and a NOT EXISTS condition in two different tables.
IF NOT EXISTS (SELECT 1 FROM `categories` WHERE categories.term_id = 123)
AND EXISTS (SELECT 1 FROM `terms` WHERE terms.id = 123)
THEN INSERT INTO `categories`(id, term_id, term_type_id)
VALUES ('', '123', '4')
Thanks in advance.
You an use indices to enforce this behavior.
EXISTS (SELECT 1 FROMtermsWHERE terms.id = 123)
To enforce this, define categories.term_id as a foreign key to terms.id.
That way you can not insert a term_id into the categories table if that is non existent in the terms table.
IF NOT EXISTS (SELECT 1 FROMcategoriesWHERE categories.term_id = 123)
To enforce this, you need to put a UNIQUE index on the categories.term_id column. This will block duplicate entries.
You can first check the desired record from the table with a select query. If the query returns the 0 rows then execute the insert statement otherwise no need to insert.

multiple values insert join in mysql

I have a query submitting multiple items in table a.
For example:
insert into a values(id,name) (5,'john'),(6,'smith');
Though I also need to select some third value from other table with this id.
For example:
insert into a values(id,name,money) (5,'john',(select money from b where id=5)),(6,'smith',(select money from b where id=6));
The problem with the above is that it's a bit repetitive and also uses sub selects.
I wonder if it's possible to rewrite this using JOIN, (which should also reassure that there is a relation to the table b on that given id, lest it inserts a NULL).
Any ideas?
You're allowed only one SELECT for each INSERT so you need to re-write this to select multiple rows, not insert multiple values at once. Could you create a temporary table with the two sets of values in it and INSERT those with a JOIN?
CREATE TEMPORARY TABLE _tmp_a (id INT PRIMARY KEY, name VARCHAR(255));
INSERT INTO _tmp_a (5, 'john'), (6, 'smith')
INSERT INTO a (id, name, money) SELECT _tmp_a.id, _tmp_a.name, b.money FROM _tmp_a LEFT JOIN b ON b.id=_tmp_a.id

INSERT INTO with SubQuery MySQL

I have this Statement:
INSERT INTO qa_costpriceslog (item_code, invoice_code, item_costprice)
VALUES (1, 2, (SELECT item_costprice FROM qa_items WHERE item_code = 1));
I'm trying to insert a value copy the same data of item_costprice, but show me the error:
Error Code: 1136. Column count doesn't match value count at row 1
How i can solve this?
Use numeric literals with aliases inside a SELECT statement. No () are necessary around the SELECT component.
INSERT INTO qa_costpriceslog (item_code, invoice_code, item_costprice)
SELECT
/* Literal number values with column aliases */
1 AS item_code,
2 AS invoice_code,
item_costprice
FROM qa_items
WHERE item_code = 1;
Note that in context of an INSERT INTO...SELECT, the aliases are not actually necessary and you can just SELECT 1, 2, item_costprice, but in a normal SELECT you'll need the aliases to access the columns returned.
You can just simply e.g.
INSERT INTO modulesToSections (fk_moduleId, fk_sectionId, `order`) VALUES
((SELECT id FROM modules WHERE title="Top bar"),0,-100);
I was disappointed at the "all or nothing" answers. I needed (again) to INSERT some data and SELECT an id from an existing table.
INSERT INTO table1 (id_table2, name) VALUES ((SELECT id FROM table2 LIMIT 1), 'Example');
The sub-select on an INSERT query should use parenthesis in addition to the comma as deliminators.
For those having trouble with using a SELECT within an INSERT I recommend testing your SELECT independently first and ensuring that the correct number of columns match for both queries.
Your insert statement contains too many columns on the left-hand side or not enough columns on the right hand side. The part before the VALUES has 7 columns listed, but the second part after VALUES only has 3 columns returned: 1, 2, then the sub-query only returns 1 column.
EDIT: Well, it did before someone modified the query....
As a sidenote to the good answer of Michael Berkowski:
You can also dynamically add fields (or have them prepared if you're working with php skripts) like so:
INSERT INTO table_a(col1, col2, col3)
SELECT
col1,
col2,
CURRENT_TIMESTAMP()
FROM table_B
WHERE b.col1 = a.col1;
If you need to transfer without adding new data, you can use NULL as a placeholder.
If you have multiple string values you want to add, you can put them into a temporary table and then cross join it with the value you want.
-- Create temp table
CREATE TEMPORARY TABLE NewStrings (
NewString VARCHAR(50)
);
-- Populate temp table
INSERT INTO NewStrings (NewString) VALUES ('Hello'), ('World'), ('Hi');
-- Insert desired rows into permanent table
INSERT INTO PermanentTable (OtherID, NewString)
WITH OtherSelect AS (
SELECT OtherID AS OtherID FROM OtherTable WHERE OtherName = 'Other Name'
)
SELECT os.OtherID, ns.NewString
FROM OtherSelect os, NewStrings ns;
This way, you only have to define the strings in one place, and you only have to do the query in one place. If you used subqueries like I initially did and like Elendurwen and John suggest, you have to type the subquery into every row. But using temporary tables and a CTE in this way, you can write the query only once.