SQL Server : INSERT with a condition - sql

I want to insert into my Files-Favorites table only if the values I'm trying to pass isn't in there already.
I tried:
INSERT INTO [Files-Favorites](fileID,auditorID)
VALUES ('1', '34')
WHERE (fileID != '1'
AND auditorID != '34')
This doesn't work. I'm trying not to INSERT duplicate values. How do I pull this off? This is for a Microsoft SQL Server 2005.
Thank you

Try using if not exists
IF NOT EXISTS(SELECT * FROM [Files-Favorites] WHERE fileID = '1' AND auditorID = '34')
BEGIN
INSERT INTO [Files-Favorites](fileID, auditorID)
VALUES('1', '34')
END

I would use a composite (multi-column) key rather than checking on each insert
ALTER TABLE [Files-Favorites] ADD CONSTRAINT unique_1 UNIQUE(fileID,auditorID)

We can use EXISTS with sub query to check the data existence and insert accordingly:
INSERT INTO [Files-Favorites](fileID,auditorID)
SELECT fileID, auditorID FROM (
SELECT '1' fileID,'34' auditorID) t
WHERE NOT EXISTS(SELECT tm.fileID FROM [Files-Favorites] tm
WHERE tm.fileID = t.fileID AND tm.auditorID = t.auditorID)

Related

Using sequence while inserting data into 2 tables at same time

I am trying to insert data using select statement. The table which I am inserting is having foreign key and it is sequence ID. How do I accomplish this? Because if I insert the sequence key in associated table first then how do I get the list of all the sequence ID to insert into the table.
Please note I am using insert with select statement so is there way to accomplish this without using cursor?
I think you can extract sequence value and then re-use it as many times as you want:
DECLARE #NextValue INT
SELECT #NextValue = NEXT VALUE FOR MySequence
SELECT NextValue = #NextValue
INSERT INTO PrimaryTable(PK_ID) VALUES (#NextValue);
INSERT INTO SecondaryTable(FK_ID) VALUES (#NextValue);
Here what I have tried.
DECLARE #MyTabVaR TABLE
(
FOREIGNKEY_ID INT,
COMMON_COL INT
);
INSERT INTO #MyTabVaR
SELECT NEXT VALUE FOR DBO.MY_SEQ,COMMON_COL FROM another_table2
INSERT INTO actual_table
SELECT FOREIGNKEY_ID FROM #MyTabVaR
INSERT INTO another_table
SELECT * FROM copy_table C
LEFT JOIN actual_table A
ON C.COMMON_COL=A.COMMON_COL
WHERE A.FOREIGNKEY_ID IS NOT NULL

How to write a check to avoid the message "INSERT statement conflicted with the FOREIGN KEY constraint"?

I read and understood the entries in following asked question: INSERT statement conflicted with the FOREIGN KEY constraint
. I do get the point, however, I'm in this situation where I have around 1 Gb of records need to be inserted into a table, some of those records have conflicted foreign key. The query looks like this:
IF NOT EXISTS (SELECT * FROM [dbo].[tbl_R_TaskHistory] WHERE [TaskID] =
10000529)
BEGIN insert into [dbo].[tbl_History]
([TaskID],[UserID],[ActD],[RequestD],[No],[SignID],[Completed])
values (10000529,'A0000187',NULL,5738366,0,NULL,CAST(N'2011-03-16
04:53:37.210' AS DateTime)) END
The conflict ocurs on RequestID, so I was thinking there must be a way to make a check to avoid the error messages.
My point is that I want my query to check if the RequestID has not FOREIGN KEY constraint it will not insert this record and move to the next one.
If your query contains only one row, you can just expand the check like this:
IF NOT EXISTS (SELECT * FROM [dbo].[tbl_R_TaskHistory] WHERE [TaskID] = 10000529) AND EXISTS(SELECT 1 FROM [dbo].[...referencing table...] WHERE [RequestD] = 5738366)
BEGIN
insert into [dbo].[tbl_History] ([TaskID],[UserID],[ActD],[RequestD],[No],[SignID],[Completed])
values (10000529,'A0000187',NULL,5738366,0,NULL,CAST(N'2011-03-16 04:53:37.210' AS DateTime));
END
Anyway, if you are inserting many rows at the same time and for performance considerations, it will be better to store the values in buffer table. Something like this:
insert into #tbl_History ([TaskID],[UserID],[ActD],[RequestD],[No],[SignID],[Completed])
values (10000529,'A0000187',NULL,5738366,0,NULL,CAST(N'2011-03-16 04:53:37.210' AS DateTime))
,(...)
,(...)
,(...)
Then, just perform an inner join to your referencing table:
insert into [dbo].[tbl_History] ([TaskID],[UserID],[ActD],[RequestD],[No],[SignID],[Completed])
SELECT [TaskID],[UserID],[ActD],[RequestD],[No],[SignID],[Completed]
FROM #tbl_History A
INNER JOIN [dbo].[...referencing table...] B
ON A.[RequestD] = B.[RequestD];
This syntax also works
declare #a int = 5;
declare #b int = 18;
insert into sample (a, b)
select #a, #b
where not exists (select 1 from sample where b = #b)
and exists (select 1 from student where iden = #a)
This avoids creating a #temp
insert into sample (a, b)
select a, b
from ( values (5,19)
, (5,30)
, (5,31)
, (5,32)
, (7,41)
, (7,42)
) v(a,b)
where not exists (select 1 from sample where b = v.b)
and exists (select 1 from student where iden = v.a)

SQL - Insert Where Not Exists

I have what I thought to be a completely trivial query - insert values into a table if a value with a matching ID does not exist:
BEGIN
INSERT INTO [dbo].[Contact_Categories](Contact_Category_ID, Description)
VALUES (1, 'Internal')
WHERE NOT EXISTS( SELECT * FROM [dbo].[Contact_Categories] WHERE Contact_Category_ID = 1)
END
I get an error around the where statement. Why? How do I accomplish my goal?
Your problem comes from WHERE being valid for UPDATE/SELECT but INSERT just doesn’t understand what it means.
But you can get around this. Change your code to be like:
BEGIN
INSERT INTO [dbo].[Contact_Categories](Contact_Category_ID, Description)
SELECT 1, 'Internal'
WHERE NOT EXISTS( SELECT * FROM [dbo].[Contact_Categories] WHERE Contact_Category_ID = 1)
END
The correct way to handle this is by using a unique index/constraint:
create unique index unq_Contact_Categories_Category_Id on Contact_Categories(Contact_Category_ID);
The database will then guarantee the uniqueness for the column. This prevents race conditions.
You can catch this using try/catch:
BEGIN TRY
INSERT INTO [dbo].[Contact_Categories](Contact_Category_ID, Description)
SELECT 1, 'Internal';
END TRY
BEGIN CATCH
PRINT 'Ooops'; -- you can even raise an error if you like.
END CATCH;
Why not an If statement?
IF NOT EXISTS
(select * from [dbo].[Contact_Categories] WHERE Contact_Category_ID = 1)
begin
insert into [dbo].[Contact_Categories] (Contact_Category_ID, Description)
values (1, 'Internal')
end
This has the advantage of not doing anything if the value exists. Similar to answer provided here: SQL Server IF NOT EXISTS Usage?
I would do:
INSERT INTO [dbo].[Contact_Categories](Contact_Category_ID, Description)
VALUES (1, 'Internal')
WHERE 1 NOT IN ( SELECT Contact_Category_ID FROM [dbo].[Contact_Categories])
Try to replace your query with:
BEGIN
IF NOT EXISTS (SELECT * FROM [dbo].[Contact_Categories] WHERE Contact_Category_ID = 1)
INSERT INTO [dbo].[Contact_Categories](Contact_Category_ID,Description) VALUES (1, 'Internal')
END
I also had the same problem, this is my solution.
insert into Contact_Categories (Contact_Category_ID, Description)
select 1, 'Internal'
where not exists
(select * from Contact_Categories where Contact_Category_ID = 1 and Description = 'Internal');

Insert into a Informix table or update if exists

I want to add a row to an Informix database table, but when a row exists with the same unique key I want to update the row.
I have found a solution for MySQL here which is as follows but I need it for Informix:
INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE name="A", age=19
You probably should use the MERGE statement.
Given a suitable table:
create table table (id serial not null primary key, name varchar(20) not null, age integer not null);
this SQL works:
MERGE INTO table AS dst
USING (SELECT 1 AS id, 'A' AS name, 19 AS age
FROM sysmaster:'informix'.sysdual
) AS src
ON dst.id = src.id
WHEN NOT MATCHED THEN INSERT (dst.id, dst.name, dst.age)
VALUES (src.id, src.name, src.age)
WHEN MATCHED THEN UPDATE SET dst.name = src.name, dst.age = src.age
Informix has interesting rules allowing the use of keywords as identifiers without needing double quotes (indeed, unless you have DELIMIDENT set in the environment, double quotes are simply an alternative to single quotes around strings).
You can try the same behavior using the MERGE statement:
Example, creation of the target table:
CREATE TABLE target
(
id SERIAL PRIMARY KEY CONSTRAINT pk_tst,
name CHAR(1),
age SMALLINT
);
Create a temporary source table and insert the record you want:
CREATE TEMP TABLE source
(
id INT,
name CHAR(1),
age SMALLINT
) WITH NO LOG;
INSERT INTO source (id, name, age) VALUES (1, 'A', 19);
The MERGE would be:
MERGE INTO target AS t
USING source AS s ON t.id = s.id
WHEN MATCHED THEN
UPDATE
SET t.name = s.name, t.age = s.age
WHEN NOT MATCHED THEN
INSERT (id, name, age)
VALUES (s.id, s.name, s.age);
You'll see that the record was inserted then you can:
UPDATE source
SET age = 20
WHERE id = 1;
And test the MERGE again.
Another way to do it is create a stored procedure, basically you will do the INSERT statement and check the SQL error code, if it's -100 you go for the UPDATE.
Something like:
CREATE PROCEDURE sp_insrt_target(v_id INT, v_name CHAR(1), v_age SMALLINT)
ON EXCEPTION IN (-100)
UPDATE target
SET name = v_name, age = v_age
WHERE id = v_id;
END EXCEPTION
INSERT INTO target VALUES (v_id, v_name, v_age);
END PROCEDURE;

Check if data exist update else insert in SQL Server linked server

I try to insert data from table in another. I want to check all rows, if row exists, just update, if row does not exist, insert it (based on ID).
I have this insert statement:
insert into d1.dbo.UrlRecord (EntityId, EntityName, Slug, IsActive, LanguageId)
select
Id, 'Category',
REPLACE(Name, ' ', '-'), 1, 0
from d2.dbo.Category
if Id exist just update with new value else insert
I want to make it run dynamically using job in SQL Server
Try the following MERGE script
MERGE d1.dbo.UrlRecord TT
USING
(
SELECT
Id,'Category' as EntityName,REPLACE(Name,' ','-') as Slug,1 as IsActive,0 as LanguageID
FROM d2.dbo.Category
)ST on TT.EntityId = ST.id
WHEN NOT MATCHED THEN
INSERT ( EntityId,EntityName,Slug,IsActive,LanguageId)
VALUES (ST.Id,ST.EntityName,ST.Slug, ST.IsActive,ST.LanguageID)
WHEN MATCHED THEN
UPDATE
SET
TT.EntityName = ST.EntityName,
TT.Slug = ST.Slug,
TT.IsActive = ST.IsActive,
TT.LanguageId=ST.LanguageID
;