Inserting multiple rows in one table with just one insert commnad - sql

A little hard to explain in SQL terms because I am using an in-house technology but Let's say I have an array of a structs (similar to structs we have in C#, C++, etc) and I want to insert its values in a table.
So one way is a psedu-code that iterates through the array, read the fields of the structs and inserts them into the table like this:
for int i =1 to array.Lenght
{
insert into MyTable values
{
MyTable.Field1 = array[i].Field1;
//etc ...
}
}
but this is bad, because of performnce. If array has ten elements we are calling insert method ten times.
There should be a brillinat way of doing this with just one insert, somehow using JOINS on table and just call insert one time, But I can't imagine how to do that...
Any thoughts on this are welcome.
Thanks.

Insert multiple records into MySQL with a single query:
INSERT INTO example
(example_id, name, value, other_value)
VALUES
(100, 'Name 1', 'Value 1', 'Other 1'),
(101, 'Name 2', 'Value 2', 'Other 2'),
(102, 'Name 3', 'Value 3', 'Other 3'),
(103, 'Name 4', 'Value 4', 'Other 4');
http://www.electrictoolbox.com/mysql-insert-multiple-records/

This makes sure the query is executed once. This is just an idea, avoiding multiple call insert
#sql = 'insert into mytable(col_1) values'
for int i =1 to array.Lenght
{
if(i > 1)
#sql = ',('+#sql + array[i].Field1+')'
else
#sql = '('+#sql + array[i].Field1+')'
}
#sql = #sql + ';'
exec #sql
Script looks like
insert into mytable(col_1) values
(1),(2),(3);

Related

Something wrong in Preprending string with spaces

Based on the suggestion in this post Right pad a string with variable number of spaces
For testing purposes, I created a table and added the following rows
CREATE TABLE CharTest (
ID int,
CharField char(6) NULL
);
INSERT INTO CharTest
VALUES (1, ' 90');
INSERT INTO CharTest
VALUES (1, ' 89');
INSERT INTO CharTest
VALUES (1, NULL);
INSERT INTO CharTest
VALUES (1, ' 91');
INSERT INTO CharTest
VALUES (1, ' 90');
I then tried executing this query
DECLARE #lCharField char(6)
SET #lCharField = '90'
SELECT CharField FROM CharTest
where CharField = RIGHT(space(6) + #lCharField, 6)
it returned no rows.
I checked the output of the following queries
SELECT RIGHT(space(6) + #lCharField, 6) FROM CharTest
SELECT RIGHT(' ' + #lCharField, 6) FROM CharTest
and it doesn't seem to right-pad or pre-prend the spaces as expected.
Any help in pointing out what I am doing wrong is highly appreciated.
The issue is this code:
DECLARE #lCharField char(6);
SET #lCharField = '90';
You think the result is '90' but it is really '90 '. That throws everything off. Use:
DECLARE #lCharField varchar(6);
SET #lCharField = '90';
Here is a db<>fiddle.
Note that finicky spaces are one important reason why varchar() is used -- say -- 100 times more often than char(). The only really good use for char() is for columns that are of fixed width, such as ISO3 code for counties.

Postgresql - Compare a string with a null value

I'm a bit puzzled because I believe the answer to this question is fairly simple but I've searched and tried several options and couldn't find the right answer.
The database is a PostgreSQL 13.1
I am using an API which sends a JSON object to a stored function in the database as follows:
select * from api.car_model_create( '{
"payload": {
"manufacturer": "ai3ZV7PzbP5dNo2fb9q9QGjj2nS5aWJm",
"name": "SR22",
"variant": "G2",
"subname": null
},
"stk": "YbtmjypXMqXb1U5WOq53DxkaxrbIxl4X"
}'::json
);
The function queries a table with the following structure:
CREATE TABLE app.car_models (
id INTEGER NOT NULL
, public_id CHARACTER(32) DEFAULT (api.random_string(32))
, name CHARACTER VARYING(64) NOT NULL
, variant CHARACTER VARYING(64)
, subname CHARACTER VARYING(64)
, designator CHARACTER VARYING(16)
, manufacturer INTEGER NOT NULL
, car_type INTEGER
, status INTEGER NOT NULL DEFAULT 1
) WITHOUT OIDS TABLESPACE app;
Inside the function is a query like this:
SELECT count(*)
FROM app.car_models am, app.business_entities be
WHERE am.manufacturer=be.id
AND be.public_id=$1
AND lower(am.name) = lower($2)
AND lower(am.variant) = lower($3)
AND lower(am.subname) = lower($4);
Everything works as expected until one of the values of "variant" or "subname" is passed as NULL.
These two are the $3 and $4 in the query. The table accepts null values for these two columns.
If the value of "variant" or "subname" passed by the JSON object is null the query doesn't return any result even if the row exists in the table. I must be missing something really simple or basic. But I can't find it.
EDIT TO ADD A MINIMUM REPRODUCIBLE EXAMPLE:
CREATE TABLE car_models (
id INTEGER NOT NULL
, name CHARACTER VARYING(64) NOT NULL
, variant CHARACTER VARYING(64)
, subname CHARACTER VARYING(64)
);
INSERT INTO car_models VALUES (1, 'Name 1', 'Variant 1', 'Subname 1');
INSERT INTO car_models VALUES (2, 'Name 2', 'Variant 2', 'Subname 2');
INSERT INTO car_models VALUES (3, 'Name 3', NULL, 'Subname 3');
INSERT INTO car_models VALUES (4, 'Name 4', 'Variant 4', NULL);
SELECT count(*)
FROM car_models
WHERE lower(name) = lower('Name 4')
AND lower(variant) = lower('Variant 4')
AND lower(subname) = lower(null);
Postgres supports standard null-safe equality operator is distinct from, which does exactly what you ask for:
SELECT count(*)
FROM car_models
WHERE lower(name) IS NOT DISTINCT FROM lower('Name 4')
AND lower(variant) IS NOT DISTINCT FROM lower('Variant 4')
AND lower(subname) IS NOT DISTINCT FROM lower(null);
Demo on DB Fiddle:
| count |
| ----: |
| 1 |
Side note: do you really need lower() here? It is not obvious from your sample data. Note that using this function prevents the database from taking advantage of an index (unless you do create an index on this specific expression).

MS SQL INSERT INTO trouble

I need to insert new record in table.
The first column name ob_no is int, not null. So I need generate number which is maximum ob_no at the moment +1. How can I do it? Something Like (max(ob_no) + 1) but it doesn't work in SQL 2005. Thanks for any ideas.
INSERT INTO et_thanks_2014 (ob_no, c_name)
VALUES (???, 'Some Text')
You should use identities if you don't need values without lag:
INSERT INTO et_thanks_2014 (ob_no, c_name)
SELECT MAX(ob_no) + 1, 'Some Text'
FROM et_thanks_2014

Why this insert query go into error?

I am very new to Microsoft SQL Server and I have a problem with this INSERT query that inserts a new record in a very very big table (it has many columns).
I have this query:
INSERT INTO VulnerabilityAlertDocument ([Id],
[VulnerabilityAlertId],
[SourceId],
[BugTraqID],
[Title],
[StatusID],
[CVE],
[Published],
[LastUpdated],
[Remote],
[Local],
[Credibility],
[Classification],
[Availability],
[Ease],
[Authentication],
[CVSS2_BaseScore],
[CVSS2_TemporalScore],
[CVSS2_BaseVector],
[CVSS2_TemporalVector],
[CVSS1_BaseScore],
[CVSS1_TemporalScore],
[NVD_CVSS2_BaseScore],
[NVD_CVSS2_ComponentString],
[ImpactRating],
[Severity],
[EaseofExploit],
[UrgencyRating],
[LastChange],
[ShortSummary],
[Impact],
[TechnicalDescription],
[AttackScenario],
[Exploit],
[Credit],
[URL],
[AlertStatusId],
[Type],
[DetailLevel],
[Language],
[dd])
VALUES('10000',
'10000',
'TEST',
'5',
'TEST TITLE',
'1',
'TEST CVE',
'1998-04-30 00:00:00.000',
'2007-11-05 16:32:34.000',
'TEST REMOTE',
'TEST LOCAL',
'TEST CREDIBILITY',
'TEST CLASSIFICATION',
'TEST Availability',
'TEST EASE',
'TEST Authentication',
'TEST CVSS2_BaseScore',
'TEST VSS2_TemporalScore',
'TEST CVSS2_BaseVector',
'TEST VSS2_TemporalVector',
'TEST CVSS1_BaseScore',
'TEST CVSS1_TemporalScore',
'TEST NVD_CVSS2_BaseScore',
'TEST NVD_CVSS2_ComponentString',
'2',
'3',
'10',
'7',
'TEST LastChange',
'TEST ShortSummary',
'TEST IMPACT',
'TEST TechnicalDescription',
'TEST AttackScenario',
'TEST Exploit',
'TEST Credit',
'TEST URL',
'5',
'3',
'1',
'TEST Language',
'NULL');
In which I insert a specific value into a specified column (I specify columns by the first query section, and I specify the related values by the second section of the query)
The problem is that when I try to execute the previous query I obtain the following error
Msg 544, Level 16, State 1, Line 1
Cannot insert explicit value for identity column in table 'VulnerabilityAlertDocument' when
IDENTITY_INSERT is set to OFF.
Why? What does this mean? How can I change my query to solve this problem and so insert the record in my table?
Try SET IDENTITY_INSERT VulnerabilityAlertDocument ON before INSERT
After INSERT, add SET IDENTITY_INSERT VulnerabilityAlertDocument OFF
you have an identity column then you don't have to insert the Id, you have to delete Id from your query and the value of the Id
Remove the [Id] column from the list of columns and its corresponding value '10000'. The error is due you are trying to populate a column with a value and SQL is complaining that a automated handled value just he can provide.
BTW, you don't need to quote your numeric values if that columns are of numeric type.
Use SET IDENTITY_INSERT ON before your query.
Identity columns are auto-increasing and so do not allow insertion.
You need to explicitly state that you want to insert data into the column so that SQL server allows it.
Make sure you do not insert duplicate values for this column.
The best practice is to avoid inserting values into IDENTITY column.
Remove "[ID]"
write it like that:
INSERT INTO your table name
For example:
If you have Instructor table with attributes ID, name and dept_name
Use: Insert Command like bellow
Insert Into Instructor (ID, name, dept_name) Values (11111, 'Andrea', 'Biology');
Try this and let me show you result !!

Creating a stored procedure to insert specific data into 1-2 tables

I have two tables,
Idea(Idea_ID int primary key, Idea_name varchar(30))
And
Keyword(Idea_ID int, Keyword varchar(15), weight numeric(1,0))
I am looking to create a stored procedure which inserts data into the Idea and/or the Keyword table. The format of the input would ideally be (Idea_name, K1,W1,K2,W2,K3,W3...etc) with Ks being Keywords and Ws being the weight.
I would like it so that if the Idea name can't be found in the Idea table, a new Idea name is first inserted into the Idea table, and then the other data inserted into the Keyword table. Is it also possible to have the stored procedure check the input pattern to make sure it has the correct formatting and the correct data types, showing a string if there is an issue?
Thanks in advance for the help, I am quite new to stored procedures and the MSSQL freetext search engine! Are there any other relevant tags I could include?
Cheers
Please don't use a comma separated list, there are much better ways of doing this, in my opinion there is no place for delimited strings in SQL.
If you are using SQL-Server 2008 or later then you can use table valued parameters to pass your keywords to the store procedure:
CREATE TYPE dbo.KeyWords AS TABLE (Keyword VARCHAR(15) NOT NULL, Weight NUMERIC(1, 0));
Your procedure would then be something like
CREATE PROCEDURE dbo.SaveIdea #IdeaName VARCHAR(30), #Keywords dbo.KeyWords READONLY
AS
DECLARE #IdeaID INT = ( SELECT TOP 1 Idea_ID
FROM dbo.Idea
WHERE Idea_Name = #IdeaName
);
IF #IdeaID IS NULL
BEGIN
INSERT dbo.Idea (Idea_Name) VALUES (#IdeaName);
SET #IdeaID = SCOPE_IDENTITY();
END
MERGE dbo.KeyWords t
USING #Keywords s
ON t.Idea_ID = #IdeaID
AND t.Keyword = s.Keyword
WHEN NOT MATCHED THEN INSERT (Idea_ID, KeyWord, Weight)
VALUES (#IdeaID, s.Keyword, s.Weight)
WHEN MATCHED AND t.Weight != s.Weight THEN UPDATE
SET Weight = s.Weight
OUTPUT $Action, inserted.*;
GO
The first check is to see if an idea exists with that name, if it does no new row is inserted, otherwise a new idea is added. It then Merges the keywords. If they already exist for that idea they are not added, but if the weight is different this is updated. If they keyword doesn't exist it is inserted.
Then to use this you can use something like:
DECLARE #Keywords dbo.KeyWords;
INSERT #Keywords (Keyword, Weight)
VALUES
('Test 1', 1),
('Test 2', 2),
('Test 3', 3),
('Test 4', 5),
('Test 5', 4);
EXECUTE dbo.SaveIdea 'Test Idea', #Keywords;
SELECT *
FROM dbo.Idea;
SELECT *
FROM dbo.Keywords;
SQL Fiddle
Although this is more practical to call from your application layer.