There are a few questions that look a lot like the question below, but i can't find a proper answer.
I want to do an insert in table b, for example ID_b,ID_a, name, name2.
I only want to do the insert if the ID_a exists in table a
Simple question, leading to a headache.
You can use a single insert-select statement for this.
E.g., assume your values for [ID_b, ID_a, name, name2] are [1, 100, 'name', 'name2']:
INSERT INTO b (ID_b, ID_a, name, name2)
SELECT 1, ID_a, 'name', 'name2'
FROM a
WHERE ID_a = 100
If ID_a = 100 exists, the new row will be inserted. If it does not, zero rows will selected from table a, and thus, nothing will inserted into b.
Related
I want to insert values from different sources. For example
insert into a (('id','name','add'),'college')
select from b where id = 1,'abc'
Here there is no timestamp field in table b
I would rewrite your query as follows:
insert into a (id, name, add, college)
select id, name, add, 'abc' from b where id = 1
With this query, the 4th column in a will be assigned a constant value of 'abc'.
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
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.
Suppose I have two tabels, A and B, each with three columns (A.id, A.title, A.text and B.id, B.a_id, B.text). B.a_id is a foreign key to relates to A.id. Now, suppose there is one record in A (1, 'foo', 'bar') and 2 records in B (1, 1, 'test') and (2, 1, 'test1').
My question is, is there a standard method of copying the record in A, and, at the same time copying all the records from B that relate to A. So suppose I create a new record in A (2, 'foo', 'bar') that's based on (1, 'foo', 'bar'), is there some sort of method that creates two new records in B (3, 2, 'test') and (4, 2, 'test1)?
I've never used triggers before, is this the correct moment to start doing that? Or is this a very stupid question?
this is not a stupid question. However, I believe that this is not possible with pure SQL, or only with some exotic syntax that I am not aware of. Copying rows is not the problem (assuming that id is auto_increment):
insert into A (title, text) select title, text from A where id = XY
However, then you need to find the last insert ID to duplicate the records in B. Let's see:
insert into B (a_id, text) select LAST_INSERT_ID(), text from B where a_id = XY
Hm... maybe this works, but I am a bit sceptical about the LAST_INSERT_ID(). Anyway, I don't think it can be done with just one statement.
Let me know how it goes
Tom
I'm having a little trouble with a selection and I was figuring I could either look for help in solving the selection or find a better way to model my data. My tables are structured such that:
Table A( a_id, a2, a3, a4) pk: a_id
Table B( b_id, a_id, b3) pk: b_id, a_id
Table B can have any number of entries for each b_id, but only one for each b_id, a_id. I want to be able to reference the set for each b_id to check for their existence so that the set is not duplicated. For example, say I had a tuple in table C
Table C( c_id, b_id ) pk:c_id
with a reference to a b_id of 1. If another tuple was to be inserted into C which results in the insertion of the same set represented by a b_id of 1 into table B, I would want the new tuple to have a b_id of 1, as well, instead of inserting into table B and using that b_id.
edit:
See this sqlfiddle. Say I wanted to insert a new object which is represented by the following inserts:
INSERT INTO B VALUES (3, 1, 2);
INSERT INTO B VALUES (3, 2, 11;
INSERT INTO B VALUES (3, 3, 5);
INSERT INTO C VALUES (2,3);
How can I query the database (or restructure) so that I can realize that the sets in Table B represented by a b_id of 1 or 3 would be the same? I would then want to change my logic so that the object being inserted is represented by the single statement:
INSERT INTO C VALUES (2,1);
A real-world-like example:
Imagine a player in a game. Each player in the game is a tuple in Table C. Each player can where any number of clothes - Table B. A piece of clothing is defined by the part of the body it covers (Table A) and its color (b3)
I want to find the player wearing a specific set of clothing. Lets say that player wore that same set again - I shouldnt have to add more data to table B, I should be able to say he wore it last game, so we'll just reference that set of clothing
You need programming language eg PHP to loop all the conditions:
SELECT B.b_id, BB.num, count(*)
FROM B, (
SELECT b_id, count(*) num
FROM B
WHERE (a_id=1 and b3=1)
OR (a_id=2 and b3=11)
OR (a_id=3 and b3=5)
OR (a_id=4 and b3=6)
-- you need programming language eg php to loop all your set data here
GROUP BY 1
) as BB
WHERE B.b_id = BB.b_id
GROUP BY 1,2
HAVING count(*) = 4 and count(*) = BB.num
-- count(*) should be manually input to match above loop of OR
The sub-query get b_id and count, join back with B to match if they are exactly same.
Which means, you need to provide exactly same set of values [a_id, b3] to get correct value of b_id, not sub-set, not sup-set, exactly match.
In your example data, if you want to return bid=1, you need provide 3 sets of [aid,b3); if you want to return bid=2, you need to provide 4 sets of [aid,b3]
If b_id, a_id do not constitute a unique identity for table B then you don't really have a pk.
Anyways, adding UNIQUE (a_id, b3) to your table B definition will prevent the duplicate entry values:
INSERT INTO B VALUES (3, 1, 2);
INSERT INTO B VALUES (3, 2, 8);
INSERT INTO B VALUES (3, 3, 10);
A foreign key constraint would then prevent:
INSERT INTO C VALUES (2,3);
But I don't think this approach is sufficient for what you are trying to do. For example would the insert into B above be ok if the existing records for B included another record, say 1, 5, 20?