Clearly the following is incorrect.
INSERT INTO `aTable` (`A`,`B`) VALUES((SELECT MAX(`A`) FROM `aTable`)*2),'name');
I get the value:
SQL query:
INSERT INTO `aTable` (`A`, `B` )
VALUES
(
(
SELECT MAX(`A`)
FROM `aTable`
) *2
, 'name'
)
MySQL said:
1093 - You can't specify target table 'aTable' for update in FROM clause
So, I'm trying to make a bitmap table, each row corresponds to one Bit, and has a 'map' value.
To insert in the table, I don't want to do two queries, I want to do one.
How should I do this?
No one commented on this, but since I am trying to make a bitmap, it should be * 2 not ^ 2, my mistake, please note that is why the comments often say ^ 2, it was an error in the version that the commenters read.
try:
insert into aTable select max(a)^2, 'name' from aTable;
or
insert into aTable select max(a)^2, 'name' from aTable group by B;
If you need a join, you can do this:
insert into aTable select max(a)^2, 'name' from aTable, bTable;
My "Server version" is "5.0.51b-community-nt MySQL Community Edition (GPL)"
Actually, you can alias the table on the insert. I've seen this question all over the place, but no one seems to have tried that. Use a subquery to get the max from the table, but alias the table in the subquery.
INSERT INTO tableA SET fieldA = (SELECT max(x.fieldA) FROM tableA x)+1;
A more complex example, where you have a corresponding secondary key and might be inserting the FIRST record for the corresponding secondary key:
INSERT INTO tableA SET secondaryKey = 123, fieldA = COALESCE((SELECT max(x.fieldA) FROM tableA x WHERE x.secondaryKey = 123)+1,1);
By aliasing the table, it doesn't throw the error and seems to work. I just did this while coding something, although I can't see if there area any silly syntax errors above, I would try that type of syntax.
I take it that INSERT ... SELECT isn't working? I see this in the documentation for it:
The target table of the INSERT
statement may appear in the FROM
clause of the SELECT part of the
query. (This was not possible in some
older versions of MySQL.) In this
case, MySQL creates a temporary table
to hold the rows from the SELECT and
then inserts those rows into the
target table.
Out of curiosity, which version of MySQL are you using?
I think you need to drop the "VALUES", and have a valid select statement.
see this link
I'm not particularly a mySQL guy, I use MSSQL mostly. But If you format the select statement correctly, It should work.
as soon as the Select is correct you can do this.
Related
In SQL is it possible to nest a SELECT statement in the VALUES clause of the INSERT statement? I'm using MySQL and would like to query the table for the max value of a field plus one when creating a new record, as shown below.
INSERT into attornies (
LawOfficeId, LawOfficeName
) VALUES (
(select max(LawOfficeID)+1 from attornies),
'Wee, Sue Em and Howe'
);
I'm not sure if my syntax is bad, what I'm trying to do is not possible, etc. Of course, If I try this as two separate statements it works but I would like to make it one statement. I know one suggestion is to use auto increment but I don't want to.
If this question has already been answered please point me in that direction. If not .... Help.
Yes you can do it
INSERT into attornies (
LawOfficeId, LawOfficeName
)
select max(LawOfficeID) + 1,'Wee, Sue Em and Howe' from attornies;
However this is not recommended over auto increment since you are likely going to run into duplicate primary key situation if multiple threads are doing the insert
Your query should work. Scalar subqueries are allowed in the values clause of the insert.
In general, it would more commonly be written as:
insert into attornies (LawOfficeId, LawOfficeName)
select max(LawOfficeID)+1, 'Wee, Sue Em and Howe'
from attornies;
However, this is not the right way to do what you seem to want. Instead, create attornies -- which I am renaming to lawOffices because that seems to be the intention -- with an auto-increment column:
create table lawOffices (
lawOfficeId int auto_increment primary key,
lawOfficeName varchar(255)
);
And then do:
insert into lawOffices (lawOfficeName)
values ( 'Wee, Sue Em and Howe' );
The database does the work of incrementing the id.
You can't use the syntax you show.
mysql> INSERT into attornies (
-> LawOfficeId, LawOfficeName
-> ) VALUES (
-> (select max(LawOfficeID)+1 from attornies),
-> 'Wee, Sue Em and Howe'
-> );
ERROR 1093 (HY000): You can't specify target table 'attornies' for update in FROM clause
https://dev.mysql.com/doc/refman/8.0/en/subquery-errors.html says:
You can use a subquery for assignment within an UPDATE statement because subqueries are legal in UPDATE and DELETE statements as well as in SELECT statements. However, you cannot use the same table (in this case, table t1) for both the subquery FROM clause and the update target.
The doc is talking about using a subquery in an UPDATE statement, but the same rule applies in an INSERT or DELETE statement.
However, this works:
mysql> INSERT into attornies (
-> LawOfficeId, LawOfficeName
-> )
-> select max(LawOfficeID) + 1,'Wee, Sue Em and Howe' from attornies;
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
https://dev.mysql.com/doc/refman/8.0/en/insert-select.html says:
The target table of the INSERT statement may appear in the FROM clause of the SELECT part of the query. However, you cannot insert into a table and select from the same table in a subquery.
When selecting from and inserting into the same table, MySQL creates an internal temporary table to hold the rows from the SELECT and then inserts those rows into the target table.
I agree with the other answers and comments who warn you against using the MAX()+1 method of getting the next id value. This method is susceptible to race conditions. Use an auto-increment column instead.
Okay, you've all convinced me. In addition, I did a bit of testing of import/export with an auto-increment field in MySQL. My concerns are no longer justified. I'll discard my max()+1 idea as unnecessary and go with auto-increment.
I would also like to thank Steve, Bill Karwin and Gordon Linoff for correcting my SQL and pointing me in the proper direction if I had continued with my original idea.
I'm using the mysql node module.
My query is:
insert into myTableA (fk_1, fk_2)
values (
(select id from myTableB where name = ?),
(select id from myTableC where name = ?)
)
My method call looks like:
db.query(q, [values], (err) => { ... })
Each item in values is an array whose items are respectively the names in myTableB and myTableC. As shown above, I made sure to wrap values in another array.
The error I get is:
ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ...`
Help please...
EDIT 1:
The values I am trying to insert look like the following:
var values = [
[name00, name01],
[name10, name11],
[name20, name21],
...
]
EDIT 2:
Here's to clarify my confusion... Basically, I am looking for a way that would allow me to use the INSERT INTO query to combine the following 2 queries:
INSERT INTO MyTable (col_1, col_2, col_3) VALUES ?
and:
INSERT INTO MyTableA (col_1, col_2, col_3) VALUES (
(select id from MyTableB where name=?),
(select id from MyTableC where name=?),
?
)
The query I am looking for would let me pass a values variable in the following form:
var values = [
[row_0_col_1, row_0_col_2, row_0_col_3],
[row_1_col_1, row_1_col_2, row_1_col_3],
[row_2_col_1, row_2_col_2, row_2_col_3],
...
]
myTableA appears to be a many-to-many table, and you're trying to populate the rows to be foreign keys references to myTableB and myTableC.
With the INSERT ... VALUES syntax, you can specify rows of data values, but each row must be specified. Like this:
INSERT INTO myTableA (fk_1, fk_2) VALUES
('name00', 'name01');
('name10', 'name11');
('name20', 'name21');
Each row is independent and self-contained. If you use subqueries, each subquery must return a single value (this is called a scalar subquery). You can't use subqueries that return multiple values.
You can also use INSERT ... SELECT syntax, so instead of listing rows one by one, the INSERT just uses the rows returned by a SELECT statement.
INSERT INTO myTableA (fk_1, fk_2)
SELECT b.id, c.id
FROM myTableB JOIN myTableC ON (...);
But you would have to provide some join expression to describe how to match values from the two respective tables in the join.
This would require inventing the many-to-many relationship out of thin air.
As for the syntax error returned by node, the error you included in your post above is truncated where you typed .... This isn't a complete error message. The query you posted is obviously edited (I suppose your table names are not myTableA, myTableB, etc.). You're asking for help but you have provided neither the real query you executed, nor the real error message. Given that, there's no way for anyone on Stack Overflow to guess at the cause of the error, or any fix for it.
Try using SQL Join feature, to insert the selected values from multiple tables.
An example for your reference:
INSERT INTO Table (aID, bID)
SELECT a.ID, B.ID
FROM A, B
WHERE A.Name='Me'
AND B.Class='Math';
I have this mysql syntax:
INSERT INTO `utilizatori`(
utilizator
)
SELECT
'Mama'
FROM
`utilizatori`
WHERE
NOT EXISTS (SELECT `utilizator` FROM `utilizatori` WHERE utilizator='Mama')
utilizatori is a table, utilizator is a column, Mama is a value
This syntax will insert a value in table only if it doesnt exist.If the value exist it wont create it,so until now it works fine,but if there is no 'Mama' value,then it will insert it...the only problem is that it will insert it multiple times.For example if i have 4 rows,it will insert 'Mama' value 4 times,creating 4 rows.Any idea??
I would make the task easier, clearer by making utilizator field unique.
That way when you add new rows with existing value 'Mama' for utilizator in this case: mysql returns error with the code: 1062, and don't let user have multiple rows with Mama in the table.
So when you run query:
INSERT INTO `utilizatori` (utilizator) VALUES ('Mama')
You can check if MySQL returns any error, but better to check number of affected rows, if insert was successful it will be equal to 1 otherwise 0.
Checking mechanism depends what language and driver you use for connecting to database.
Since you had PHP tag selected you may be using PDO than
$statement->rowCount(); // $statement = PDOStatement, I assume you know this thing well
will give you desired result
Final simple example:
...
if ($statement->rowCount())
{
echo "Cool! You have been added to database";
}
else
{
echo "Hmms! Are you trying to duplicate something?";
}
Try to use group by :
INSERT INTO `utilizatori`(
utilizator
)
SELECT
'Mama'
FROM
`utilizatori`
WHERE
NOT EXISTS (SELECT `utilizator` FROM `utilizatori` WHERE utilizator='Mama')
group by utilizator
You are basically doing:
SELECT ... WHERE NOT EXISTS
...and inserting this in your table. As stated in the comments, just make your utilizator field unique and drop the whole SELECT part from your query.
Where Column is missing...
INSERT INTO `utilizatori`(
utilizator
)
SELECT
'Mama'
FROM
`utilizatori`
WHERE
'Mama'
NOT EXISTS (SELECT `utilizator` FROM `utilizatori` WHERE utilizator='Mama')
Is it possible to do something like this (obviously this syntax does not work):
SELECT a FROM (1, 2, 3)
to get this:
| a |
+---+
| 1 |
| 2 |
| 3 |
?
That is I want to make rows from coma separated list, without using any table, or at least without creating table in db (maybe this is possible using something like temporary table?).
Maybe it is possible to get column of given values without using select, that is using some other sql statment? If it is not possible in MySQL, but possible in some other SQL it still would be interesting to know.
SELECT 1 a UNION ALL SELECT 2 a UNION ALL SELECT 3 a;
Would a temporary table be an option? Then I would have a suggestion which, admittedly, has more than 1 query:
-- DROP TEMPORARY TABLE tmp_list IF EXISTS;
CREATE TEMPORARY TABLE tmp_list (a INT);
INSERT INTO tmp_list (a) VALUES (1), (2), (3);
SELECT a FROM tmp_list;
If it is not possible in MySQL, but possible in some other SQL it still would be interesting to know.
In standard SQL this would be something like this
select *
from ( values (1), (2), (3) ) t
This works at least in PostgreSQL and DB2.
In PostgreSQL you can give the column a name by extending the alias (not sure if that column aliasing is part of the SQL standard).
select *
from ( values (1), (2), (3) ) t (id)
The following is an alternative to the above using a common table expression.
with my_values (id) as (
values (1), (2), (3)
)
select *
from my_values;
Since MariaDB v10.3.3 and MySQL v8.0.19 you can now do exactly that!
See docs: MariaDB, MySQL
MariaDB:
WITH mylist (a) AS (VALUES (1),(2),(3))
SELECT a FROM mylist
I used a WITH here because MariaDB doesn't supply nice column names for VALUES .... You can use it in a union without column names:
SELECT 1 AS a UNION ALL VALUES (2),(3)
And although the docs don't appear to mention it, you can even use it as a top-level query:
VALUES (1),(2),(3) ORDER BY 1 DESC
The actual column names are in fact the just first row of values, so you can even do this (though it's inelegant, and you can run into duplicate column name errors):
SELECT `4` AS a FROM (VALUES (4),(5),(6)) mylist
MySQL:
I don't have an instance of MySQL v8.0.19 to test against right now, but according to the docs [EDIT: Tested successfully on MySQL v8.0.23 using dbfiddle.uk, see links in comment #2] either of these should work:
SELECT column_0 AS a FROM (VALUES ROW(1), ROW(2), ROW(3)) mylist
SELECT a FROM (VALUES ROW(1), ROW(2), ROW(3)) mylist(a)
Unlike MariaDB, MySQL supplies automatic column names column_0, column_1, column_2, etc., and also supports renaming all of a subquery's columns when referencing it.
I'm not sure, but this dev worklog page seems to suggest that MySQL has also implemented [EDIT: not implemented yet, as of v8.0.26] the shorter sytax (omitting "ROW", like MariaDB), or that they might at some poiint in the near future.
Trying to duplicate some rows in a table but just change the ssreportid column from 4 to 6:
INSERT INTO ssreportparticipant (ssreportid, sssurveyparticipantid)
VALUES
SELECT 6, sssurveyparticipantid FROM ssreportparticipant
WHERE ssreportid = 4
The error says #1064 near 'select 6, ...' but if I just run the select clause, it selects the records perfectly, with the new id of 6 in the ssreportid column.
The table has a primary key called ssreportparticipantid, and there is a unique key on (ssreportid, sssurveyparticipantid). Note that the select clause creates new records that have unique key pairs, so that's not the problem. I have tried putting brackets around the select clause, and even using two aliases for the table, no joy.
Using server version 5.0.45.
Please tell me that programmer fatigue has me missing a comma or something.
Thanks,
-Josh
I think you should remove "VALUES"
I am not sure, but maybe it is possible that you cannot insert into a table with a select from the same table. Have you tried to select from a different table, just for the sake of testing ?