Complicated/Simple SQL Insert: adding multiple rows - sql

I have a table connecting principals to their roles. I have come upon a situation where I need to add a role for each user. I have a statement SELECT id FROM principals which grabs a list of all the principals. What I want to create is something like the following:
INSERT INTO role_principal(principal_id,role_id)
VALUES(SELECT id FROM principals, '1');
so for each principal, it creates a new record with a role_id=1. I have very little SQL experience, so I dont know if I can do this as simply as I would like to or if there is some sort of loop feature in SQL that I could use.
Also, this is for a mySQL db (if that matters)

Use VALUES keyword if you want to insert values directly. Omit it to use any SELECT (where column count and type matches) to get the values from.
INSERT INTO role_principal(principal_id,role_id)
(SELECT id, 1 FROM principals);

To avoid duplicates is useful to add a subquery :
INSERT INTO role_principal(principal_id,role_id)
(SELECT id, 1 FROM principals p
WHERE NOT EXISTS
(SELECT * FROM role_principal rp WHERE rp.principal_id=p.id AND role_id=1)
)

Related

How to insert new row with id from other table in loop with Postgressql

I would like to insert new row in profit table for each user that exist in db: select id * from users. The number of users is dynamic, so I need to fetch them all. I need some loop in postgres sql. I have problem to figure it out on my own. It would be something like that:
select id * from users as user_ids
for (each userId in user_ids) {
insert into profit (user_id, value) values (userId, 23);
}
Can I ask You for help? I've went for many questions already:
Insert new row with data computed from other rows
postgresSQL insert multiple rows, of id returned from select queries
No luck so far
Thinking in "loops" is almost always wrong when working with SQL. You need to think in terms of sets and how you operate on them. SQL statement describe exactly that: how to retrieve a set and what to do with that set of rows.
In this case, you can use a SELECT statement as the source for an INSERT:
insert into profit (user_id, value)
select id, 23
from users;
Note that you don't have a values clause in this case.

Get Id from a conditional INSERT

For a table like this one:
CREATE TABLE Users(
id SERIAL PRIMARY KEY,
name TEXT UNIQUE
);
What would be the correct one-query insert for the following operation:
Given a user name, insert a new record and return the new id. But if the name already exists, just return the id.
I am aware of the new syntax within PostgreSQL 9.5 for ON CONFLICT(column) DO UPDATE/NOTHING, but I can't figure out how, if at all, it can help, given that I need the id to be returned.
It seems that RETURNING id and ON CONFLICT do not belong together.
The UPSERT implementation is hugely complex to be safe against concurrent write access. Take a look at this Postgres Wiki that served as log during initial development. The Postgres hackers decided not to include "excluded" rows in the RETURNING clause for the first release in Postgres 9.5. They might build something in for the next release.
This is the crucial statement in the manual to explain your situation:
The syntax of the RETURNING list is identical to that of the output
list of SELECT. Only rows that were successfully inserted or updated
will be returned. For example, if a row was locked but not updated
because an ON CONFLICT DO UPDATE ... WHERE clause condition was not
satisfied, the row will not be returned.
Bold emphasis mine.
For a single row to insert:
Without concurrent write load on the same table
WITH ins AS (
INSERT INTO users(name)
VALUES ('new_usr_name') -- input value
ON CONFLICT(name) DO NOTHING
RETURNING users.id
)
SELECT id FROM ins
UNION ALL
SELECT id FROM users -- 2nd SELECT never executed if INSERT successful
WHERE name = 'new_usr_name' -- input value a 2nd time
LIMIT 1;
With possible concurrent write load on the table
Consider this instead (for single row INSERT):
Is SELECT or INSERT in a function prone to race conditions?
To insert a set of rows:
How to use RETURNING with ON CONFLICT in PostgreSQL?
How to include excluded rows in RETURNING from INSERT ... ON CONFLICT
All three with very detailed explanation.
For a single row insert and no update:
with i as (
insert into users (name)
select 'the name'
where not exists (
select 1
from users
where name = 'the name'
)
returning id
)
select id
from users
where name = 'the name'
union all
select id from i
The manual about the primary and the with subqueries parts:
The primary query and the WITH queries are all (notionally) executed at the same time
Although that sounds to me "same snapshot" I'm not sure since I don't know what notionally means in that context.
But there is also:
The sub-statements in WITH are executed concurrently with each other and with the main query. Therefore, when using data-modifying statements in WITH, the order in which the specified updates actually happen is unpredictable. All the statements are executed with the same snapshot
If I understand correctly that same snapshot bit prevents a race condition. But again I'm not sure if by all the statements it refers only to the statements in the with subqueries excluding the main query. To avoid any doubt move the select in the previous query to a with subquery:
with s as (
select id
from users
where name = 'the name'
), i as (
insert into users (name)
select 'the name'
where not exists (select 1 from s)
returning id
)
select id from s
union all
select id from i

SQL Server 2005 T-SQL remap columns

I have an application that is ready to go live, once we take data from a MS Access DB and import it into SQL Server 2005. I have used the Migration - Access tool to get the Access db into SQL Server, but now I need to take the data from that table and put it into the tables that our app is going to use. Is there a T-Sql way to Insert multiple rows, while at the same time 're-mapping' the data?
For example
SELECT ID, FIRST_NAME, LAST_NAME
INTO prod_users (user_id, first_name, last_name)
FROM test_users
I know that select * into works when the column names are the same, but the
prod_users (column names, ..., ...)
part is what I really need to get to work.
Any ideas?
I believe the SELECT INTO syntax is used to create new tables. If you want to map data from the tables you just imported to some other existing tables, try a plain INSERT. For example:
INSERT INTO prod_users (user_id, first_name, last_name)
SELECT ID, FIRST_NAME, LAST_NAME
FROM test_users
The mapping of columns from test_users to prod_users is based on the order that they are listed, i.e. the first column in "prod_users (column_names, ...)" matches the first column in the "SELECT other_col_names, ...", the second matches the second, etc. Therefore, in the code sample above, ID is mapped to user_id, and LAST_NAME is mapped to last_name, and so on.
Just make sure you have the same number of columns in each list and that the column types match (or can be converted to match). Note that you don't have to specify all the columns in either table (as long as the destination table has valid defaults for the unspecified columns).
See the INSERT syntax for details; the part relevant to your question is the "execute_statement" expression.
INSERT and SELECT are the magic keywords:
insert into new_table (list of columns) select columnA, functionB(),
(correlated_subquery_C) from table_or_join where critera_expression_is_true
Maybe you can be more specific about what you mean by re-mapping?
Base on your comment, a more specific query is:
insert into new_table (user_id, firstname, lastname)
select id, first_name, last_name from old_database..old_table

Is there a way i can do multiple inserts into one table using a condition?

Is there a way i can do multiple inserts into one table using a condition?
i have a list of subscribers in tbl_subscribers. i have an update on productX so i would like everyone who is subscribes to productX to get a notification. The user_notification table is id PK, user_id, notification_id. The two values i need is product_id (productX) which allows me to find a list of subscribers in tbl_subscribers and the notification_id to insert into the user_notification table.
How can i do this insert using one query? I see you can do a select statement in sqlite http://www.sqlite.org/lang_insert.html but i cannot wrap my head around how i may do this nor seen an example.
I believe you're looking from INSERT SELECT as outlined here:
http://www.1keydata.com/sql/sqlinsert.html
The second type of INSERT INTO allows
us to insert multiple rows into a
table. Unlike the previous example,
where we insert a single row by
specifying its values for all columns,
we now use a SELECT statement to
specify the data that we want to
insert into the table. If you are
thinking whether this means that you
are using information from another
table, you are correct. The syntax is
as follows:
INSERT INTO "table1" ("column1", "column2", ...)
SELECT "column3", "column4", ... FROM "table2"
insert into user_notification(user_id, notification_id)
select s.user_id, #notification_id
from tbl_subscriber s
where s.product_id = #productX

MySQL Insert query doesn't work with WHERE clause

What's wrong with this query:
INSERT INTO Users( weight, desiredWeight ) VALUES ( 160, 145 ) WHERE id = 1;
It works without the WHERE clause. I've seemed to have forgot my SQL.
MySQL INSERT Syntax does not support the WHERE clause so your query as it stands will fail. Assuming your id column is unique or primary key:
If you're trying to insert a new row with ID 1 you should be using:
INSERT INTO Users(id, weight, desiredWeight) VALUES(1, 160, 145);
If you're trying to change the weight/desiredWeight values for an existing row with ID 1 you should be using:
UPDATE Users SET weight = 160, desiredWeight = 145 WHERE id = 1;
If you want you can also use INSERT .. ON DUPLICATE KEY syntax like so:
INSERT INTO Users (id, weight, desiredWeight) VALUES(1, 160, 145) ON DUPLICATE KEY UPDATE weight=160, desiredWeight=145
OR even like so:
INSERT INTO Users SET id=1, weight=160, desiredWeight=145 ON DUPLICATE KEY UPDATE weight=160, desiredWeight=145
It's also important to note that if your id column is an autoincrement column then you might as well omit it from your INSERT all together and let mysql increment it as normal.
You can't combine a WHERE clause with a VALUES clause. You have two options as far as I am aware-
INSERT specifying values
INSERT INTO Users(weight, desiredWeight)
VALUES (160,145)
INSERT using a SELECT statement
INSERT INTO Users(weight, desiredWeight)
SELECT weight, desiredWeight
FROM AnotherTable
WHERE id = 1
You use the WHERE clause for UPDATE queries. When you INSERT, you are assuming that the row doesn't exist.
The OP's statement would then become;
UPDATE Users SET weight = 160, desiredWeight = 45 where id = 1;
In MySQL, if you want to INSERT or UPDATE, you can use the REPLACE query with a WHERE clause. If the WHERE doesn't exist, it INSERTS, otherwise it UPDATES.
EDIT
I think that Bill Karwin's point is important enough to pull up out of the comments and make it very obvious. Thanks Bill, it has been too long since I have worked with MySQL, I remembered that I had issues with REPLACE, but I forgot what they were. I should have looked it up.
That's not how MySQL's REPLACE works. It does a DELETE (which may be a no-op if the row does not exist), followed by an INSERT. Think of the consequences vis. triggers and foreign key dependencies. Instead, use INSERT...ON DUPLICATE KEY UPDATE.
I do not believe the insert has a WHERE clause.
Insert query doesn't support where keyword*
Conditions apply because you can use where condition for sub-select statements.
You can perform complicated inserts using sub-selects.
For example:
INSERT INTO suppliers
(supplier_id, supplier_name)
SELECT account_no, name
FROM customers
WHERE city = 'Newark';
By placing a "select" in the insert statement, you can perform multiples inserts quickly.
With this type of insert, you may wish to check for the number of rows being inserted. You can determine the number of rows that will be inserted by running the following SQL statement before performing the insert.
SELECT count(*)
FROM customers
WHERE city = 'Newark';
You can make sure that you do not insert duplicate information by using the EXISTS condition.
For example, if you had a table named clients with a primary key of client_id, you could use the following statement:
INSERT INTO clients
(client_id, client_name, client_type)
SELECT supplier_id, supplier_name, 'advertising'
FROM suppliers
WHERE not exists (select * from clients
where clients.client_id = suppliers.supplier_id);
This statement inserts multiple records with a subselect.
If you wanted to insert a single record, you could use the following statement:
INSERT INTO clients
(client_id, client_name, client_type)
SELECT 10345, 'IBM', 'advertising'
FROM dual
WHERE not exists (select * from clients
where clients.client_id = 10345);
The use of the dual table allows you to enter your values in a select statement, even though the values are not currently stored in a table.
See also How to insert with where clause
The right answer to this question will be sth like this:
a). IF want select before insert :
INSERT INTO Users( weight, desiredWeight )
select val1 , val2 from tableXShoulatNotBeUsers
WHERE somecondition;
b). IF record already exists use update instead of insert:
INSERT INTO Users( weight, desiredWeight ) VALUES ( 160, 145 ) WHERE id = 1;
Should be
Update Users set weight=160, desiredWeight=145 WHERE id = 1;
c). If you want to update or insert at the same time
Replace Users set weight=160, desiredWeight=145 WHERE id = 1;
Note):- you should provide values to all fields else missed field in query
will be set to null
d). If you want to CLONE a record from SAME table, just remember you cann't select
from table to which you are inserting therefore
create temporary table xtable ( weight int(11), desiredWeight int(11) ;
insert into xtable (weight, desiredWeight)
select weight, desiredWeight from Users where [condition]
insert into Users (weight, desiredWeight)
select weight , desiredWeight from xtable;
I think this pretty covers most of the scenarios
You simply cannot use WHERE when doing an INSERT statement:
INSERT INTO Users( weight, desiredWeight ) VALUES ( 160, 145 ) WHERE id = 1;
should be:
INSERT INTO Users( weight, desiredWeight ) VALUES ( 160, 145 );
The WHERE part only works in SELECT statements:
SELECT from Users WHERE id = 1;
or in UPDATE statements:
UPDATE Users set (weight = 160, desiredWeight = 145) WHERE id = 1;
A way to use INSERT and WHERE is
INSERT INTO MYTABLE SELECT 953,'Hello',43 WHERE 0 in (SELECT count(*) FROM MYTABLE WHERE myID=953);
In this case ist like an exist-test. There is no exception if you run it two or more times...
I think that the correct form to insert a value on a specify row is:
UPDATE table SET column = value WHERE columnid = 1
it works, and is similar if you write on Microsoft SQL Server
INSERT INTO table(column) VALUES (130) WHERE id = 1;
on mysql you have to Update the table.
Insert into = Adding rows to a table
Upate = update specific rows.
What would the where clause describe in your insert?
It doesn't have anything to match, the row doesn't exist (yet)...
You can do conditional INSERT based on user input.
This query will do insert only if input vars '$userWeight' and '$userDesiredWeight' are not blank
INSERT INTO Users(weight, desiredWeight )
select '$userWeight', '$userDesiredWeight'
FROM (select 1 a ) dummy
WHERE '$userWeight' != '' AND '$userDesiredWeight'!='';
If you are looking to insert some values into a new column of an altered table in each rows by mentioning its primary key, then just-->
UPDATE <table_name> SET <column_name> = '<value> WHERE <primary_key> = <primary_value>
It depends on the situation INSERT can actually have a where clause.
For example if you are matching values from a form.
Consider INSERT INTO Users(name,email,weight, desiredWeight) VALUES (fred,bb#yy.com,160,145) WHERE name != fred AND email != bb#yy.com
Makes sense doesn't it?
The simplest way is to use IF to violate your a key constraint. This only works for INSERT IGNORE but will allow you to use constraint in a INSERT.
INSERT INTO Test (id, name) VALUES (IF(1!=0,NULL,1),'Test');
After WHERE clause you put a condition, and it is used for either fetching data or for updating a row. When you are inserting data, it is assumed that the row does not exist.
So, the question is, is there any row whose id is 1? if so, use MySQL UPDATE, else use MySQL INSERT.
If you are specifying a particular record no for inserting data its better to use UPDATE statement instead of INSERT statement.
This type of query you have written in the question is like a dummy query.
Your Query is :-
INSERT INTO Users( weight, desiredWeight ) VALUES ( 160, 145 ) WHERE id = 1;
Here , you are specifying the id=1 , so better you use UPDATE statement to update the existing record.It is not recommended to use WHERE clause in case of INSERT.You should use UPDATE .
Now Using Update Query :-
UPDATE Users SET weight=160,desiredWeight=145 WHERE id=1;
Does WHERE-clause can be actually used with INSERT-INTO-VALUES in any
case?
The answer is definitively no.
Adding a WHERE clause after INSERT INTO ... VALUES ... is just invalid SQL, and will not parse.
The error returned by MySQL is:
mysql> INSERT INTO Users( weight, desiredWeight ) VALUES ( 160, 145 ) WHERE id = 1;
ERROR 1064 (42000): 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 'WHERE id = 1' at line 1
The most important part of the error message is
... syntax to use near 'WHERE id = 1' ...
which shows the specific part the parser did not expect to find here: the WHERE clause.
its totall wrong. INSERT QUERY does not have a WHERE clause, Only UPDATE QUERY has it. If you want to add data Where id = 1 then your Query will be
UPDATE Users SET weight=160, desiredWeight= 145 WHERE id = 1;
No. As far as I am aware you cannot add the WHERE clause into this query. Maybe I've forgotten my SQL too, because I am not really sure why you need it anyway.
You Should not use where condition in Insert statement. If you want to do, use insert in a update statement and then update a existing record.
Actually can i know why you need a where clause in Insert statement??
Maybe based on the reason I might suggest you a better option.
I think your best option is use REPLACE instead INSERT
REPLACE INTO Users(id, weight, desiredWeight) VALUES(1, 160, 145);
DO READ THIS AS WELL
It doesn't make sense... even literally
INSERT means add a new row and when you say WHERE you define which row are you talking about in the SQL.
So adding a new row is not possible with a condition on an existing row.
You have to choose from the following:
A. Use UPDATE instead of INSERT
B. Use INSERT and remove WHERE clause ( I am just saying it...) or if you are real bound to use INSERT and WHERE in a single statement it can be done only via INSERT..SELECT clause...
INSERT INTO Users( weight, desiredWeight )
SELECT FROM Users WHERE id = 1;
But this serves an entirely different purpose and if you have defined id as Primary Key this insert will be failure, otherwise a new row will be inserted with id = 1.
I am aware that this is a old post but I hope that this will still help somebody, with what I hope is a simple example:
background:
I had a many to many case: the same user is listed multiple times with multiple values and I wanted to Create a new record, hence UPDATE wouldn't make sense in my case and I needed to address a particular user just like I would do using a WHERE clause.
INSERT into MyTable(aUser,aCar)
value(User123,Mini)
By using this construct you actually target a specific user (user123,who has other records) so you don't really need a where clause, I reckon.
the output could be:
aUser aCar
user123 mini
user123 HisOtherCarThatWasThereBefore
correct syntax for mysql insert into statement using post method is:
$sql="insert into ttable(username,password) values('$_POST[username]','$_POST[password]')";
i dont think that we can use where clause in insert statement
INSERT INTO Users(weight, desiredWeight )
SELECT '$userWeight', '$userDesiredWeight'
FROM (select 1 a ) dummy
WHERE '$userWeight' != '' AND '$userDesiredWeight'!='';
You can't use INSERT and WHERE together. You can use UPDATE clause for add value to particular column in particular field like below code;
UPDATE Users
SET weight='160',desiredWeight ='145'
WHERE id =1
You can do that with the below code:
INSERT INTO table2 (column1, column2, column3, ...)
SELECT column1, column2, column3, ...
FROM table1
WHERE condition
I think you should do it like this, if you want to validate table not to use email twice
Code :
INSERT INTO tablename(fullname,email)
SELECT * FROM (SELECT 'fullnameValue' AS fullname_field,'emailValue' AS email_field) entry WHERE entry.email_field NOT IN (SELECT email FROM tablename);
All the above answers give you the plain MySQL statements.
If you are using the where condition in PHPMyAdmin to update the existing row of a table, below is the suggestion to use.
UPDATE `Table_Name` SET `row1`='[value-1]',`row2`='[value-2]',`row3`='[value-3]' WHERE 1
You can include any value between '' of each row. Not necessarily to put [] to indicate the value. Do not change anything after where. Simply click go after giving the value to update.
Example:
UPDATE `Mytable_name` SET `abc`='xyz',`def`='uvw'
WHERE 1