Insert values from a list in a single SQL statement - sql

I have a list with values in it. I want to insert these values in a SQL table using a single INSERT statement.
Example: Say, there is a list with names (the size of the list is not constant). There is a STUDENTS table with NAME column. I want to insert in the STUDENTS table the names from the list using a single INSERT statement.
Right now I loop through the list and insert the value in the table. That means, the number of insert statements is equal to the length of the list.
List<String> Name;
foreach (String s in Name)
{
INSERT INTO STUDENTS (NAME) VALUES (s)
}
Is there a way I can accomplish this in a single SQL INSERT statement? Any help is much appreciated.

In MySql you can do it like this
INSERT INTO tbl (f1,f2) VALUES(1,2),(3,4),(5,6)...(55,77);
For mssql dialect all the same

Union can be used to achieve this, though technically each union is it's own statement.
short demo:
create table #i(hello int)
insert into #i select 1 union all select 2
select * from #i
drop table #i
There are other / better ways of populating tables from lists...those depend on what database you are on.

To do this with a single INSERT is with a SELECT.. you'd have to convert your list into this:
INSERT STUDENTS(NAME)
SELECT 'Tom'
UNION ALL
SELECT 'Bill'
UNION ALL
SELECT 'Sarah'

If your list was in a temporary table, you could use the following syntax:
insert into tblname
(columnlist)
select name from temptable;

with string.join
private void insertInto(string tablename, List<Values> list)
{
context.Database.ExecuteSqlRaw($#"INSERT INTO {tablename}(number,comment) VALUES
{string.Join(',',list.ToArray().Select(r =>$"
({r.value},'{r.comment}')").ToList())}");
returns list data and result : VALUES(1,'hello'),(5,'hello2').....

Related

How to get a key from another table in a insert into... Values SQL statement?

I am not very experienced in SQL statements and I am trying to combine a couple of statements to have less traffic to the db.(and to make sure no other actions can happen inbetween)...
I have two tables:
Table: R_LOTS
a.o. 2 columns: PK_R_LOT and LOTCODE
Table: R_LOTTRACKING
Columns: FK_R_LOT,TIMESTAMP,FK_MAGLOCATIES
I use the statement:
INSERT INTO R_LOTTRACKING (FK_R_LOT,TIMESTAMP,FK_MAGLOCATIES) VALUES (?,CURRENT_TIMESTAMP,?).
On the questionmarks I can fill in the values to send.
However, as you can imagine, I do not have the FK_R_LOT but I have the LOTCODE (of R_LOT).. Of course I can get the FK_R_LOT with a seperate SELECT PK_R_LOT FROM R_LOT WHERE LOTCODE=?; but is there a way to combine these statements?
I have seen some examples but then all information seems to come from the R_LOT table but I could not find a combination of VALUES and SELECT.
Summary:
I know: LOTCODE and FK_MAGLOCATIES
How to combine the statements to insert the row:
INSERT INTO R_LOTTRACKING (FK_R_LOT,TIMESTAMP,FK_MAGLOCATIES) VALUES (?,CURRENT_TIMESTAMP,?)
SELECT PK_R_LOT FROM R_LOT WHERE LOTCODE=?
Use a subquery:
INSERT INTO R_LOTTRACKING ( FK_R_LOT, ... )
VALUES ( (SELECT PK_R_LOT FROM R_LOT WHERE LOTCODE = ?), ... );
or use an insert select:
INSERT INTO R_LOTTRACKING ( FK_R_LOT, ... )
SELECT PK_R_LOT, ... FROM R_LOT WHERE LOTCODE = ?;

Use inserted value as a parameter for other inserts

There is a db2 database with two tables. The first one, table1, has autoincrement column ID. It is the foreign key for the table2.
A am writing an HTML generator for SQL queries. So with some input parameters it generates a query or multiple queries. It is not connected to the database.
What I need is to get that autoincrement field and use it in next queries.
So basically, the scenario is:
insert into table1;
select autogenerated field ID;
insert into table2 using that ID;
insert into table2 using that ID;
...some more similar inserts...
insert into table2 using that ID;
And all that SQL query should be generated and then used as a single SQL script.
I was thinking about something like this:
SELECT ID FROM FINAL TABLE (INSERT INTO Table1 (t1column1, t1column2, etc.)
VALUES (t1value1, t1value2, etc.))
But I don't know, how I can write the result into a variable so I could use it in next queries like this:
INSERT INTO Table2 (foreignKeyCol, t2column1, t2column2, etc.)
VALUES ($ID, t2value1, t2value2, etc.)
I could just paste that select instead of $ID, but the second query can be used several times with the same $ID and different values.
EDIT: DB2 10.5 on Linux.
You can chain several inserts together using CTEs, like so:
WITH idcte (id) as (
SELECT ID FROM FINAL TABLE (
INSERT INTO Table1 (t1column1, t1column2, etc.)
VALUES (t1value1, t1value2, etc.)
)
),
ins1 (id) as (
SELECT foreignKeyCol FROM FINAL TABLE (
INSERT INTO Table2 (foreignKeyCol, t2column1, t2column2, etc.)
SELECT id, t2value1, t2value2, etc.
FROM idcte
)
),
-- more CTEs
SELECT foreignKeyCol FROM FINAL TABLE (
-- your last INSERT ... SELECT FROM
)
Essentially you will have to wrap each INSERT into a SELECT FROM FINAL TABLE for this to work.
Alternatively, you can use a global variable to keep the ID value:
CREATE VARIABLE myNewId INT;
SET myNewId = (SELECT ID FROM FINAL TABLE (
INSERT INTO Table1 (t1column1, t1column2, etc.)
VALUES (t1value1, t1value2, etc.)
));
INSERT INTO Table2 (foreignKeyCol, t2column1, t2column2, etc.)
VALUES (myNewId, t2value1, t2value2, etc.);
DROP VARIABLE myNewId;
This assumes a recent version of Db2 for LUW.

SQL Server - Contain Multiples Values

I need retrieve a value of columm with SELECT. But, I have multiple values ...
I don't know what the user go select in checkbox...
Ex:
Insert Into MyTable (dados) Values ('a1') I want the result = Angulo 1
Insert Into MyTable (dados) Values ('a2';'a3') I want the result = Angulo 2
Insert into MyTable (dados) Values ('a3'; a1) I want the result = Angulo 3; Angulo 1
Insert into MyTable (dados) Values ('a6'; 'a7'; 'a4') I want the result = Angulo 6; Angulo 7;Angulo4
I am Trying with SELECT CASE WHEN. But it still fails...
I suspect you are asking how to use the IN keyword in your SELECT statements? It is a little unclear what you are trying to do.
Try this:
SELECT *
FROM MyTable
WHERE dados IN ('a6','a7','a4')
Assuming you have a table named MyTable and a column named dados with 3 rows in that table for a6, a7 and a4, this will return all the matches (in this case, all three rows).
Good luck.
When you say:
insert into MyTable(dados)
Values ('a6', 'a7', 'a4')
You are saying "I have one column to put data into called dados." Then, you are providing three values. This will fail in any database (even apart from the fact that the semicolons should be commas).
Perhaps you want:
insert into MyTable(dados)
Values ('a6;a7;a4')
That is only one value, a string.
This suggests a denormalized database. You might want three different rows in a table, one for each value, connected together by some key.
here are some examples if you're using sql server 2008 and above:
if(OBJECT_ID('tempdb..#dados') is not null)
DROP TABLE #dados
select top 100 * INTO #dados FROM
(
values(1,2,3),
(4,5,6),
(7,8,9)
) t(a,b,c)
select * FROM #dados
INSERT INTO #dados (a,b,c)
values(11,22,33),
(44,55,66),
(77,88,99)
SELECT * FROM #dados
INSERT INTO #dados (a,b,c)
SELECT * FROM
(
values(111,222,333),
(444,555,666),
(777,888,999)
) t(a,b,c)
SELECT * FROM #dados
If you want to insert multiple rows (not columns) the syntax is
Insert Into
MyTable (dados)
Values
('a1'),
('a2')
Looks like you're trying to ask for two things.
How to insert multiple values would be done in the following way:
Insert Into MyTable (dados) Values ('a6'),('a7'),('a4')
If you want to return the actual values 'Angulo' + the number, you can use the following:
CREATE TABLE MyTable
(
Dados varchar(255)
)
Insert Into MyTable (dados) Values ('a12')
Insert Into MyTable (dados) Values ('a2'),('a3')
Insert Into MyTable (dados) Values ('a3'),('a1')
Insert Into MyTable (dados) Values ('a6'),('a7'),('a4')
SELECT 'Angulo'+ SUBSTRING(dados,PATINDEX('%[0-9]%',dados),LEN(dados))
FROM MyTable
It will find the first number (assuming it's always the first number you're after) and get the rest of them. It will then append it with the prefix 'Angulo' (e.g Angulo1, Angulo7, etc)
If these aren't what you're after. Please can you explain further what you need.

Comma separated list of values as different rows, not as fields for one row, for an SQL INSERT

I want to make many inserts in a single SQL statement, pretty much like
INSERT INTO xxx SELECT field FROM zzz
But with values I don't have in a table, and are just a list of literals.
Normal way would be executing one SQL query for each value, but if there exists a standard SQL statement, or MySQL-specific, it would be great.
insert into xxx (fields) values (values1), (values2), (values3)
eg insert into mytable (name, desc) values ('name1','desc1'), ('name2','desc2'), ('name3','desc3'), ('name4','desc4')
insert into xxx(afield)
select 'a'
union
select 'b'
union
select 'x'
will give you a table like that :
afield
a
b
x

How to combine IN operator with LIKE condition (or best way to get comparable results)

I need to select rows where a field begins with one of several different prefixes:
select * from table
where field like 'ab%'
or field like 'cd%'
or field like "ef%"
or...
What is the best way to do this using SQL in Oracle or SQL Server? I'm looking for something like the following statements (which are incorrect):
select * from table where field like in ('ab%', 'cd%', 'ef%', ...)
or
select * from table where field like in (select foo from bar)
EDIT:
I would like to see how this is done with either giving all the prefixes in one SELECT statement, of having all the prefixes stored in a helper table.
Length of the prefixes is not fixed.
Joining your prefix table with your actual table would work in both SQL Server & Oracle.
DECLARE #Table TABLE (field VARCHAR(32))
DECLARE #Prefixes TABLE (prefix VARCHAR(32))
INSERT INTO #Table VALUES ('ABC')
INSERT INTO #Table VALUES ('DEF')
INSERT INTO #Table VALUES ('ABDEF')
INSERT INTO #Table VALUES ('DEFAB')
INSERT INTO #Table VALUES ('EFABD')
INSERT INTO #Prefixes VALUES ('AB%')
INSERT INTO #Prefixes VALUES ('DE%')
SELECT t.*
FROM #Table t
INNER JOIN #Prefixes pf ON t.field LIKE pf.prefix
you can try regular expression
SELECT * from table where REGEXP_LIKE ( field, '^(ab|cd|ef)' );
If your prefix is always two characters, could you not just use the SUBSTRING() function to get the first two characters of "field", and then see if it's in the list of prefixes?
select * from table
where SUBSTRING(field, 1, 2) IN (prefix1, prefix2, prefix3...)
That would be "best" in terms of simplicity, if not performance. Performance-wise, you could create an indexed virtual column that generates your prefix from "field", and then use the virtual column in your predicate.
Depending on the size of the dataset, the REGEXP solution may or may not be the right answer. If you're trying to get a small slice of a big dataset,
select * from table
where field like 'ab%'
or field like 'cd%'
or field like "ef%"
or...
may be rewritten behind the scenes as
select * from table
where field like 'ab%'
union all
select * from table
where field like 'cd%'
union all
select * from table
where field like 'ef%'
Doing three index scans instead of a full scan.
If you know you're only going after the first two characters, creating a function-based index could be a good solution as well. If you really really need to optimize this, use a global temporary table to store the values of interest, and perform a semi-join between them:
select * from data_table
where transform(field) in (select pre_transformed_field
from my_where_clause_table);
You can also try like this, here tmp is temporary table that is populated by the required prefixes. Its a simple way, and does the job.
select * from emp join
(select 'ab%' as Prefix
union
select 'cd%' as Prefix
union
select 'ef%' as Prefix) tmp
on emp.Name like tmp.Prefix