SQL Server How to insert multiple values while excluding repeating values - sql

I'm developing a query for a program where user has to enter one or multiple multiple values into a DB table.
The issue with the query is when you try to insert multiples values it could be that some of those values are repeated in the tables and the warning will only display one repeated value at a time and that might be a problem when you are working with a 1000+ values.
Error Message:
Cannot insert duplicate key row in object 'ItemWebCategory' with unique index 'IX_StyleID_WebCategoryID'. The duplicate key value is (1109068, 99999).
Query
insert into ItemWebCategory (Style_id,WebCategoryID)
select distinct Style_id,WebCategoryID = '99999'
from ItemCategory
where style_id in ('1109068','168175', '68435', '545457', '69189')
Question
How can I modify the query so it may skip/exclude all repeating values and only insert the values that do no exist on the table?

Try something like this:
INSERT INTO ItemWebCategory ( Style_id, WebCategoryID )
SELECT DISTINCT
Style_id,
'99999' AS WebCategoryID
FROM ItemCategory WHERE Style_id NOT IN (
SELECT Style_id FROM ItemWebCategory
);
The NOT IN excludes any Style_id values that already exist in ItemWebCategory.

You have two straight-forward options:
NOT EXISTS
insert into ItemWebCategory (Style_id,WebCategoryID)
select distinct Style_id,WebCategoryID = '99999'
from ItemCategory ic
where style_id in ('1109068','168175', '68435', '545457', '69189')
AND NOT EXISTS (SELECT 1
FROM ItemWebCategory iwc
WHERE ic.Style_id = iwc.Style_id
);
EXCEPT
insert into ItemWebCategory (Style_id,WebCategoryID)
select Style_id,WebCategoryID = '99999'
from ItemCategory
where style_id in ('1109068','168175', '68435', '545457', '69189')
EXCEPT
SELECT Style_id
FROM ItemWebCategory;
Now there's no need for DISTINCT because EXCEPT implies DISTINCT
One more useful option is a MERGE. This has performance benefits due to Halloween Protection (an entire subject in itself) as explained by Paul White:
MERGE ItemWebCategory AS target
USING (
select Style_id, WebCategoryID = '99999'
from ItemCategory
where style_id in ('1109068','168175', '68435', '545457', '69189')
) AS source
ON target.Style_id = source.Style_id
WHEN NOT MATCHED THEN INSERT
(Style_id, WebCategoryID)
VALUES (source.Style_id, source.WebCategoryID);

Related

Foreach insert statement based on where clause

I have a scenario where I have thousands of Ids (1-1000), I need to insert each of these Ids once into a table with another record.
For example, UserCars - has columns CarId and UserId
I want to INSERT each user in my Id WHERE clause against CarId 1.
INSERT INTO [dbo].[UserCars]
([CarId]
,[UserId])
VALUES
(
1,
**My list of Ids**
)
I'm just not sure of the syntax for running this kind of insert or if it is at all possible.
As you write in the comments that my list of Ids is coming from another table, you can simply use select into with a select clause
See this for more information
insert into UserCars (CarID, UserID)
select CarID, UserID
from othertable
In the select part you can use joins and whatever you need, complex queries are allowed as long as the columns in the result match the columns (CarID, UserID)
or even this to keep up with your example
insert into UserCars (CarID, UserID)
select 1, UserID
from dbo.User
if your data exists on a file, you can use BULK INSERT command, for example:
BULK INSERT UserCars
FROM '\\path\to\your\folder\users-cars.csv';
Just make sure to have the same columns structure both in the file and in the table (e.g. CarId,UserId).
Otherwise, follow #GuidoG comment to insert your data from another table:
insert into UserCars (CarID, UserID) select CarID, UserID from othertable

Insert into 2 tables with single SQL statement instead of loop

I have to insert data in provonance of several table which itself comes from csv (COPY).
Before I used a LOOP in a function to enter the data. I want to simplify the thing for the sake of maintainability and speed.
I need to insert data into a description table, which serves as both the title and description (and multi language).
Previously my code was as follows (extract from the loop):
insert into description (label, lang_id, poi_id,date_dernier_update, date_enregistrementbdd, date_derniere_lecture) values (label, lang_id, poi_id, now(), now(), now()) RETURNING id INTO _retour_id_titre;
insert into poi_titre_poi (poi_id, titre_poi_id, titre_poi_key) values (poi_id, _retour_id_titre, label_lang);
But now I can't:
with rows as (
insert into description (label, lang_id, poi_id)
select rdfslabelfrs, '1', (select id from poi where uri_id = csv_poi_rdf_fr.poi) as toto from csv_poi_rdf_fr RETURNING id
)
insert into poi_titre_poi (poi_id, titre_poi_id, titre_poi_key)
select description.poi_id, id , 'fr'
FROM description;
In fact, I cannot insert the 'poi_id' in the 'poi_titre_poi' table which corresponds to the one which was inserted in the description table.
I get this error message:
ERROR: more than one row returned by a subquery used as an expression
État SQL : 21000
Can I make this work, or do I need to loop?
Filling in missing bits with assumptions, it could work like this:
WITH description_insert AS (
INSERT INTO description
(label , lang_id, poi_id)
SELECT c.rdfslabelfrs, 1 , p.id
FROM csv_poi_rdf_fr c
JOIN poi p ON p.uri_id = c.poi
RETURNING poi_id, id
)
INSERT INTO poi_titre_poi (poi_id, titre_poi_id, titre_poi_key)
SELECT d.poi_id, d.id , 'fr'
FROM description_insert d;
Related:
PostgreSQL multi INSERT...RETURNING with multiple columns
Insert data in 3 tables at a time using Postgres
Get Id from a conditional INSERT

SQL insert data into a table from another table

I'm having a problem trying to insert some values into a table. I made an empty table with the fields
id(primary key)
association_id
resource_id
I have another table with
resource_id
association_id
and another one with
id(coresponding to the association_id in the former one)
image
I want to insert the resource_id and association_id from the first populated table, where the image field of the coresponding id from the last table is not empty.
I tried this:
INSERT IGNORE INTO `logo_associations` (``,`association_id`,`resource_id`)
SELECT
``,
`a`.`association_id`,
`a`.`resource_id`
FROM doc24_associations_have_resources a
Join doc24_associations An on a.association_id = An.id
WHERE An.image<>''
but it does not work
Try this:
INSERT INTO logo_associations (association_id, resource_id)
SELECT a.association_id
,a.resource_id
FROM doc24_associations_have_resources a
LEFT JOIN doc24_associations an ON a.association_id = an.id
WHERE an.image IS NULL -- check for null with left join
This is valid for SQL Server. You do not need to select and insert the first column as it is an identity as you mention.
My experience is based on SQL Server but the SQL may be very similar
INSERT INTO DestinationTable
(association_id, resource_id)
SELECT LNK.assocication_id,
LNK.resource_id
FROM LinkTable AS LNK
INNER JOIN ImageTable AS IMG ON IMG.id = LNK.association_id
AND IMG.image IS NOT NULL
Above I assume the following:
Tables are named DestinationTable, LinkTable, and ImageTable respectively
In DestinationTable the primary key (id) is auto generated

SQL INSERT statement for TWO TABLES at time with INNER JOIN

I have two tables hello and login_table and below is their structure
user_info
-------
some_id | name | address
login_table
-------
id | username | password
some_id and id are autoincrement indexes.
Now how can i use INSERT statement with INNER JOIN in SQL
at present, i want add below data with same some_id and id
`name` = John
`address` = wall street
`username` = john123
`password` = passw123
below code shows, what i have tried so far.
insert into login_table lt
INNER JOIN user_info ui ON ui.some_id = lt.id
(ui.name, ui.address, lt.username, lt.password)
values
('John', 'wall street', 'john123', 'passw123')
And this is not the one value, i want to add more than one value at a time.. how can i achieve.
thanks for help.
If you need to perform the two INSERT operations atomically, use a transaction:
START TRANSACTION;
INSERT INTO login_table (username, password) VALUES ('john123', 'passw123');
INSERT INTO user_info (name, address) VALUES ('John', 'wall street');
COMMIT;
N.B. Your storage engine must support transactions for this to work (e.g. InnoDB).
To insert multiple values into a table at once, use the multiple rows form of INSERT. As stated in the manual:
INSERT statements that use VALUES syntax can insert multiple rows. To do this, include multiple lists of column values, each enclosed within parentheses and separated by commas. Example:
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
The values list for each row must be enclosed within parentheses. The following statement is illegal because the number of values in the list does not match the number of column names:
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3,4,5,6,7,8,9);
VALUE is a synonym for VALUES in this context. Neither implies anything about the number of values lists, and either may be used whether there is a single values list or multiple lists.
Insert to two tables is impossible. The second part of your question is possible: you can insert multiple rows in one statement like this:
insert into some_table(col1, col2) values (1,2), (3,4), (5,6);
USE [ERPDb]
GO
INSERT INTO [AAA].[UserRole] ([UserId], [RoleId])
SELECT u.Id, (SELECT Id FROM [AAA].[Role] WHERE Title = 'Employee') FROM [AAA].[User] u
INNER JOIN [dbo].[BaseDealer] bd ON u.Id = bd.Id
WHERE bd.DealerType = 0
GO

sql insert error

This is my Insert Statement
INSERT INTO ProductStore (ProductID, StoreID, CreatedOn)
(SELECT DISTINCT(ProductId), 1, GETDATE() FROM ProductCategory
WHERE EXISTS (SELECT StoreID, EntityID FROM EntityStore
WHERE EntityType = 'Category' AND ProductCategory.CategoryID = EntityStore.EntityID AND StoreID = 1))
I am trying to Insert into table ProductStore, all the Products Which are mapped to Categories that are mapped to Store 1. Column StoreID can definitely have more than one row with the same entry. And I am getting the following error: Violation of Primary Key Constraint...
However, the Following query does work:
INSERT INTO ProductStore (ProductID, StoreID, CreatedOn)
VALUES (2293,1,GETDATE()),(2294,1,GETDATE())
So apparently, the ProductID Column is trying to insert the same one more than once.
Can you see anything wrong with my query?
TIA
I don't see any part of that query that excludes records already in the table.
Take out the INSERT INTO statement and just run the SELECT - you should be able to spot pretty quickly where the duplicates are.
My guess is that you're slightly mistaken about what SELECT DISTINCT actually does, as evidenced by the fact that you have parentheses around the ProductId. SELECT DISTINCT only guarantees the elimination of duplicates when all columns in the select list are the same. It won't guarantee in this case that you only get one row for each ProductId.
select distinct productid is selecting an existing ID and therefor in violation with your primary key constraint.
Why don't you create the primary key using Identity increment? In that case you don't need to worry about the ID itself, it will be generated for you.