The query is pasted below. Basically I have a users table, and I want to create 1 record for every entry in the users table in the controls table. I need the user_id from the users table when I'm inserting into the controls table. I get a syntax error when I try and run the query below. I've looked at a bunch of other MySQL examples that do something similar but get the same error. I'm running MySQL 5.6.21.
This will end up being a Rails migration, so I am also amenable to using ActiveRecord, but haven't really figure out how to do something like this with it.
INSERT into controls (default, whitelist, user_id, admin_status, system_status, created_at, updated_at) values (0, 0, (SELECT id FROM users), 'inactive', 'sleeping', DATE(NOW), DATE(NOW));
I believe your problem is that you're trying to mix a SELECT with VALUES (which is used for inputting literal values).
Try:
INSERT into controls
(`default`, whitelist, user_id, admin_status, system_status, created_at, updated_at)
SELECT 0, 0, id, 'inactive', 'sleeping', NOW(), NOW() FROM users;
DEFAULT is a MySQL reserved word. You may need to enclose that column name in backticks.
INSERT into controls (`default`, whitelist,
^ ^
Those are backtick characters (key to the left of the 1/! key), not single quotes.
The error message from MySQL should indicate where in the SQL text MySQL thinks the problem is.
If this is a new table, strongly consider using a column name that is not a MySQL reserved word.
Reference: https://dev.mysql.com/doc/refman/5.5/en/keywords.html
The SELECT in the context of the VALUES clause needs to return at most one row. You'd need to ensure that SELECT doesn't return more than one row, e.g. add a LIMIT 1 clause. But
Reading your question again... if you want to insert a row in the new controls table for every row that's in users table, don't use the VALUES keyword. Use the INSERT ... SELECT form of the INSERT statement.
Reference: http://dev.mysql.com/doc/refman/5.5/en/insert-select.html
Related
I have mysql query to replace some records:
REPLACE INTO product_core
(id, title, description, category_id)
VALUES (2, 'new_title', 'new_description', 33)
Can I do the same, but not providing all needed values? Example:
REPLACE INTO product_core
(id, title, description, category_id)
VALUES (2, 'new_title', 'new_description') #no category_id
Got error wrong number of values here near
I want to bulk replace many records, but I do not want to query all fields before. In this example, I want to update category_id for some records, but not for all.
REPLACE INTO product_core
(id, title, description, category_id)
VALUES (2, 'new_title_2', 'new_description_2'), #no category_id
(3, 'new_title_3', 'new_description_3', 34) #with category_id
Is it real to do this? Replace some fields for one record and other fields for second record in one query.
Or if is it real to provide special variable meaning that some fields will be the same as before replace (category_id)?
VALUES (2, 'new_title_2', 'new_description_2', #category_id_same_as_before)
Can I do the same, but not providing all needed values? Example:
REPLACE INTO product_core (id, title, description, category_id) VALUES
(2, 'new_title', 'new_description') #no category_id
Yes, the correct query is:
REPLACE INTO product_core
(id, title, description)
VALUES (2, 'new_title', 'new_description') #no category_id
EDIT: As Tom commented below the above might be misleading as for the omitted columns default values will be used, not the ones set for the record which is being replaced.
Is it real to do this? Replace some fields for one record and other fields for second record in one query.
It's not possible in MySQL. The column list is common for all the values sets.
Or if is it real to provide special variable meaning that some fields
will be the same as before replace (category_id)?
It's perhaps possible, but not straightforward and not in all MySQL versions. In the docs they say: "You cannot refer to values from the current row and use them in the new row".
In MySQL > 8.0.19 perhaps VALUES(ROW) can help. Or you can perhaps write you own UDF which does it.
You can't omit these columns from a REPLACE command, unless it is the default value for the column.
According to the documentation:
Any missing columns are set to their default values. [...] You cannot refer to values from the current row and use them in the new row.
It may be better to use a standard UPDATE command instead, which can reference the current column value.
Hi I am trying to run this query below:
INSERT INTO Database2.Table2 ('1', getdate(), getdate(), '',ID,'','0','0','0','',ID,'','',getdate(),getdate(),'','0','"stackoverflow.com/"'+'ID','0','product','','0')
SELECT ID
FROM Database1.Table1;
I am inserting a new row with constant data mixed with data from another table, this case Database1.Table1 "ID". I constantly keep getting a select statement error when I try to run this code. Is there something I am overseeing or is this statement all wrong? Thank You
Put the constants into the SELECT list.
INSERT INTO Database2.Table2
SELECT '1', getdate(), getdate(), '',ID,'','0','0','0','',ID,'','',getdate(),getdate(),
'','0',CONCAT('"stackoverflow.com/"','ID'),'0','product','','0', ID
FROM Database1.Table1;
BTW, I strongly recommend you get out of the habit of using INSERT without listing the column names before the values. Depending on the specific order of columns in the table definition is very error-prone.
Also, MySQL doesn't use + for string concatenation by default, it uses the CONCAT() function.
I am having an issue using Last_Insert_Id in a VB.NET TableAdapter Insert query wired to a MySQL database. I've read through numerous posts on this site and others regarding Last_Insert_ID and Scope_Identity, etc. None of which have worked in my case.
A little background, I have two tables, one holds login information (Auto-generated ID, username, password). Another table has a foreign key relationship on the ID values and contains ID, first name, last name, city, state.
In my TableAdapter I have an Insert query that inserts values into the first table and is supposed to return the ID value so that an Insert can be done on table 2.
Here is my Query:
INSERT INTO user_logins (user_login, user_pass)
VALUES (#p1, #p2)
I wanted to add Last_Insert_Id to make the query
INSERT INTO user_logins (user_login, user_pass)
VALUES (#p1, #p2)
SELECT LAST_INSERT_ID();
However that will only return a value of 1, regardless of what the ID is. If I open the Query Builder I get a message that states "Unable to parse query text". I tried changing the ExecuteMode to Scalar, but that didn't help either.
The Insert part is working perfectly, if I could only obtain the ID value back after insert.
Does anyone know anything I might try, or alternatively, some better way to achieve this?
Thanks!
You don't even need to use SELECT LAST_INSERT_ID();
just INSERT INTO user_logins (user_login, user_pass) VALUES (#p1, #p2) is OK
To retrieve last insert Id you can use two ways
Dim t As Integer
cmd.ExecuteNonQuery()
t = (Int32) cmd.LastInsertedId
OR
t = Convert.ToInt32(cmd.ExecuteScalar())
I am trying to go through my users table, and if the rank column is a certain value, then I want to insert a row into the messages table, with one column, "to", being the username column from the users table, and the rest of the columns in the inserted row need to be a predefined value. I'm having trouble making this work- any help?
MySQL Configuration: (Those which are needed)
Users table:
id|username|rank
Messages table:
id|to|from|body|subject
(to needs to be from the users table, from,body,and subject need to be a predefined string
I tried to figure something out like this, but it's not just quite all I need it to do. I got this code and modified it from another Stack Overflow question that was similar to this one.
INSERT INTO `messages` (`from`,`to`,`subject`,`body`)
SELECT `id`,`rank`
FROM `users`
WHERE `rank`='Super'
You can use string literals enclosed in single quotes as column values. It is safe to intermix them with the actual column values from the rows returned by the SELECT portion of your INSERT INTO...SELECT statement.
INSERT INTO `messages` (`from`, `to`, `subject`, `body)
SELECT
/* single-quote string literals to use them in the INSERT INTO...SELECT */
'Predefined string From',
/* Intermixed with column values from the rows returned by the SELECT */
`username`,
'Predefined string subject',
'Predefined string body'
FROM `users`
WHERE `rank`='Super'
If I insert multiple records with a loop that executes a single record insert, the last insert id returned is, as expected, the last one. But if I do a multiple records insert statement:
INSERT INTO people (name,age)
VALUES ('William',25), ('Bart',15), ('Mary',12);
Let's say the three above are the first records inserted in the table. After the insert statement I expected the last insert id to return 3, but it returned 1. The first insert id for the statement in question.
So can someone please confirm if this is the normal behavior of LAST_INSERT_ID() in the context of multiple records INSERT statements. So I can base my code on it.
Yes. This behavior of last_insert_id() is documented in the MySQL docs:
Important
If you insert multiple rows using a single INSERT statement, LAST_INSERT_ID() returns the value generated for the first inserted row only. The reason for this is to make it possible to reproduce easily the same INSERT statement against some other server.
This behavior is mentioned on the man page for MySQL. It's in the comments but is not challenged, so I'm guessing it's the expected behavior.
I think it's possible if your table has unique autoincrement column (ID) and you don't require them to be returned by mysql itself. I would cost you 3 more DB requests and some processing. It would require these steps:
Get "Before MAX(ID)" right before your insert:
SELECT MAX(id) AS before_max_id FROM table_name`
Make multiple INSERT ... VALUES () query with your data and keep them:
INSERT INTO table_name
(col1, col2)
VALUES
("value1-1" , "value1-2"),
("value2-1" , "value2-2"),
("value3-1" , "value3-2"),
ON DUPLICATE KEY UPDATE
Get "After MAX(ID)" right after your insert:
SELECT MAX(id) AS after_max_id FROM table_name`
Get records with IDs between "Before MAX(ID)" and "After MAX(ID)" including:
SELECT * FROM table_name WHERE id>$before_max_id AND id<=$after_max_id`
Do a check of retrieved data with data you inserted to match them and remove any records that were not inserted by you. The remaining records have your IDs:
foreach ($after_collection as $after_item) {
foreach ($input_collection as $input_item) {
if ( $after_item->compare_content($input_item) ) {
$intersection_array[] = $after_item;
}
}
}
This is just how a common person would solve it in a real world, with parts of code. Thanks to autoincrement it should get smallest possible amount of records to check against, so they will not take lot of processing. This is not the final "copy & paste" code - eg. you have to create your own function compare_content() according you your needs.