SQL - If not exists - sql

I have a table in DB where some records exist.
When I add a new record I need to check by column "Name" if the record exists in DB. If such a record does not exist - then add it, if exists - then update. I'm trying like this:
USE [TestDB]
GO
DECLARE #daily nvarchar = 'DailySummaryEmailProcessor'
IF NOT EXISTS ( SELECT *
FROM [dbo].Crons
WHERE name = #daily)
BEGIN
INSERT INTO [dbo].Crons (CronJobID, Name, Description)
VALUES()
END
ELSE
BEGIN
UPDATE [dbo].Crons
SET
WHERE
END

MERGE should fit your requirements MERGE (Transact-SQL):
MERGE Crons AS target
USING (SELECT #Name) AS source (Name)
ON (target.Name = source.Name)
WHEN MATCHED THEN
UPDATE SET target.Name = source.Name
WHEN NOT MATCHED
INSERT INTO Crons (Name) VALUES (source.Name)
OUTPUT $action, deleted.Name, inserted.Name

the issue is you never declare the size of the variable #dialy
try this and see what do you get
DECLARE #daily nvarchar = 'DailySummaryEmailProcessor'
SELECT #daily
Looks like you need to do INSERT .. UPDATE.. check out MERGE statement
https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-2017
EDIT:
Oh.. you have MySQL there in the tag. My answer is specifically on SQL Server.

Related

Enumerate the multiple rows in a multi-update Trigger

I have something like the table below:
CREATE TABLE updates (
id INT PRIMARY KEY IDENTITY (1, 1),
name VARCHAR (50) NOT NULL,
updated DATETIME
);
And I'm updating it like so:
INSERT INTO updates (name, updated)
VALUES
('fred', '2020-11-11),
('fred', '2020-11-11'),
...
('bert', '2020-11-11');
I need to write an after update Trigger and enumerate all the name(s) that were added and add each one to another table but can't work out how enumerate each one.
EDIT: - thanks to those who pointed me in the right direction, I know very little SQL.
What I need to do is something like this
foreach name in inserted
look it up in another table and
retrieve a count of the updates a 'name' has done
add 1 to the count
and update it back into the other table
I can't get to my laptop at the moment, but presumably I can do something like:
BEGIN
SET #count = (SELECT UCount from OTHERTAB WHERE name = ins.name)
SET #count = #count + 1
UPDATE OTHERTAB SET UCount = #count WHERE name = ins.name
SELECT ins.name
FROM inserted ins;
END
and that would work for each name in the update?
Obviously I'll have to read up on set based SQL processing.
Thanks all for the help and pointers.
Based on your edits you would do something like the following... set based is a mindset, so you don't need to compute the count in advance (in fact you can't). It's not clear whether you are counting in the same table or another table - but I'm sure you can work it out.
Points:
Use the Inserted table to determine what rows to update
Use a sub-query to calculate the new value if its a second table, taking into account the possibility of null
If you are really using the same table, then this should work
BEGIN
UPDATE OTHERTAB SET
UCount = COALESCE(UCount,0) + 1
WHERE [name] in (
SELECT I.[name]
FROM Inserted I
);
END;
If however you are using a second table then this should work:
BEGIN
UPDATE OTHERTAB SET
UCount = COALESCE((SELECT UCount+1 from OTHERTAB T2 WHERE T2.[name] = OTHERTAB.[name]),0)
WHERE [name] in (
SELECT I.[name]
FROM Inserted I
);
END;
Using inserted and set-based approach(no need for loop):
CREATE TRIGGER trg
ON updates
AFTER INSERT
AS
BEGIN
INSERT INTO tab2(name)
SELECT name
FROM inserted;
END

with sql how can i insert data but if it's already exists update data

I want to add it - if exists update else insert!
so that insert is working but i want to only insert new value and if thing already here i want to update it. my code here only inserts data no metter what
BEGIN
DECLARE das int;
SELECT dasaxeleba.id INTO das FROM dasaxeleba WHERE dasaxeleba.barcode = NEW.barcode;
INSERT INTO sawyobi(das_id,raodenoba,tvitgirebuleba,gasayidi1,gasayidi2)
VALUES(das,new.raodenoba,new.fasi,new.gasayidi1,new.gasayidi2);
END
if you are using oracle then you can use something like that:
merge into sawyobi tgt
using (select id
from dasaxeleba
where barcode = NEW.barcode) src on (tgt.das_id = src.id)
when matched then update set
raodenoba = new.raodenoba,
tvitgirebuleba = new.fasi,
gasayidi1 = new.gasayidi1,
gasayidi2 = new.gasayidi2
when not matched then insert
(das_id,
raodenoba,
tvitgirebuleba,
gasayidi1,
gasayidi2)
values (src.id,
new.raodenoba,
new.fasi,
ew.gasayidi1,
new.gasayidi2)
not quite sure where your "new"-values come from... but i hope you get the idea

Update and Insert Trigger

I have four tables which constantly truncate then inserts and updates data every five minutes from another system into SQL Server. So I need to create an update and insert trigger to update another in SQL Server using if exists or merge.
Select
[Barcode]
,[TradingPartnerOrderNo]
,[ProductNo]
,[BarcodeCreatedDateTime]
,[BarcodeScheduledDateTime]
,[CancelledIndicator]
,[CancelledDateTime]
,[SiteIndicator]
,[InterfaceTimeStamp]
,[OperationDate]
,[Operation]
from [dbo].[BookingView]
For me it is not very clear your demande but here is a trigger example :
CREATE TRIGGER [dbo].[up_update_mytable]
ON [dbo].[MyTable] FOR UPDATE
AS
DECLARE #ID VARCHAR(50)
SELECT #ID = ID FROM INSERTED --Use INSERTED keyword for insert and update triggers to get informations of the inserted or updated record.
UPDATE MyOtherTable SET
Column1 = 'test value',
Column2 = 'test value 2'
WHERE OtherTableID = #ID
If you are using SQL Server 2008+, then you can use MERGE to do that. Something like this:
MERGE INTO table2 AS TGT
USING
(
Select
[Barcode]
,[TradingPartnerOrderNo]
,[ProductNo]
,[BarcodeCreatedDateTime]
,[BarcodeScheduledDateTime]
,[CancelledIndicator]
,[CancelledDateTime]
,[SiteIndicator]
,[InterfaceTimeStamp]
,[OperationDate]
,[Operation]
FROM [dbo].[BookingView]
) AS SRC ON SRC.Barcode = TGT.BarCode AND
WHEN NOT MATCHED THEN
INSERT (Barcode, TradingPartnerOrderNo, ...)
VALUES (SRC.Barcode, SRC.TradingPartnerOrderNo, ...);

SQL multiple INSERT OR UPDATE

I was saving a set of values (1 record) to a table in this way:
UPDATE Table SET ...
IF ##ROWCOUNT = 0 INSERT INTO Table ...
This worked fine, but now I need to add more independent records at the same time, so I tried something like:
UPDATE Table SET ...
IF ##ROWCOUNT = 0 INSERT INTO Table ...
UPDATE Table SET ...
IF ##ROWCOUNT < 2 INSERT INTO Table ...
UPDATE Table SET ...
IF ##ROWCOUNT < 3 INSERT INTO Table ...
UPDATE Table SET ...
IF ##ROWCOUNT < 4 INSERT INTO Table ...
...in order to keep it in 1 transaction. However, starting from the 2nd declaration it adds rows even if the particular row is already existing - apparently ##ROWCOUNT does not count INSERTed rows, or I misunderstood its concept another way...
I wonder if there is some feasible way to resolve this within SQL query. In this particular case, it should be OK to assume that all records are dependent on existence of the first, but it is not 100% reliable and I would like to know a better solution, if exists.
EDIT - solution:
This may not be possible in all applications (be aware, that particular updates are not checked separately), but in my case it apears to work well and should be also consistent with the data, because the set of updated/inserted data is integral.
UPDATE Table SET ...
UPDATE Table SET ...
UPDATE Table SET ...
UPDATE Table SET ...
IF ##ROWCOUNT = 0
BEGIN
INSERT INTO Table ...
INSERT INTO Table ...
INSERT INTO Table ...
INSERT INTO Table ...
END
A slightly cleaner solution to you problem may be to use:
DECLARE #Reasons TABLE ( Name NVARCHAR(50) PRIMARY KEY, ReasonType NVARCHAR(50))
INSERT INTO #Reasons ( Name, ReasonType ) VALUES ( N'Review', N'Old Reason' )
SELECT * FROM #Reasons
MERGE INTO #Reasons AS Target
USING (VALUES
('Recommendation','Other'),
('Review', 'Marketing'),
('Internet', 'Promotion')
)
AS Source (NewName, NewReasonType)
ON Target.Name = Source.NewName
WHEN MATCHED THEN
UPDATE SET ReasonType = Source.NewReasonType
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, ReasonType) VALUES (NewName, NewReasonType) ;
SELECT * FROM #Reasons
Then you'll get all or nothing, without all of the conditions. See https://msdn.microsoft.com/en-us/library/bb510625.aspx details on the merge statement.
UPDATE TABLE .....
IF(condition)
BEGIN
/*
do insert here
*/
END
IF(condition)
BEGIN
/*
do insert here
*/
END
Source: SQL Tutorials

Using output to set a variable in a merge statement

I have a merge statement that should update or insert a single record always. I want to remember the ID of that statement in a variable. It looks like this:
DECLARE #int int
MERGE dbo.table AS A
USING (SELECT 'stringtomatch' AS string) AS B ON B.string= A.string
WHEN MATCHED THEN
UPDATE SET somecolumn = 'something'
WHEN NOT MATCHED THEN
INSERT
VALUES ('stringtomatch',
'something')
OUTPUT #int = inserted.ID;
Now this doesen't work because you can't set #int in the output clause this way. I know I could create a temptable and use INTO #temptable in the output. But since I know it's always a single record I want to have the ID in a INT variable.
Is this even possible? Or am I forced to use a table variable.
How?
No, you have to use a table variable with OUTPUT
However, you can do this...
...
WHEN MATCHED THEN
UPDATE
SET
#int = ID,
somecolumn = 'something'
WHEN NOT MATCHED THEN
INSERT
VALUES ('stringtomatch',
'something');
SET #int = ISNULL(#int, SCOPE_IDENTITY());
The "assign in UPDATE" has been a valid syntax for SQL Server for a long time. See MERGE on MSDN too. Both say this:
...<set_clause>::=
SET
...
#variable=expression