If exists (select top 1 1) with multiple instructions - sql

I have a stored procedure that checks for the existence of a record in a table and if it exists, updates the record, else, inserts a new record.
#myFieldID int = NULL,
#newTitle varchar(50) = NULL
IF EXISTS (SELECT TOP 1 1
FROM table
WHERE myField = #myFieldID)
UPDATE table1
SET title = #newTitle
WHERE myFieldID = #myFieldID
UPDATE table2
SET newTitle = #newTitle
WHERE myFieldID = #myFieldID
ELSE
INSERT INTO table1
(
title
)
SELECT #newTitle
The problem is, when I have the second UPDATE, I get an error "Incorrect syntax near the keyword 'ELSE'"
How do I update 2 tables within the same conditional "IF"? Or, do I simply have to test for the existence of the same record twice?

The issue is you're trying to multiple updates in a single IF statement with no BEGIN/END. Change your if statement to
IF EXISTS (SELECT TOP 1 1
FROM table
WHERE myField = #myFieldID)
BEGIN
UPDATE table1
SET title = #newTitle
WHERE myFieldID = #myFieldID
UPDATE table2
SET newTitle = #newTitle
WHERE myFieldID = #myFieldID
END
ELSE

Related

Automation Anywhere SQL results

I am trying to capture if my SQL Query have 0 rows or multiple rows. If it has 0 rows then I will insert, if 1 will perform an update, if > 1 will perform additional analysis.
Is there a way I can see if my query resulted in x results or no results in automation anywhere?
Any assistance will be appreciated.
You can make use of if exists and if not exists and check if rows exists or not, or even if there are multiple before doing the insert.
Here is a simple example using if not exists where if the row doesn't exist on dbo.Table it will insert a row. If it already exists then the ID will be logged to an Error table.
declare #InsertID int = 5, #Name nvarchar(max) = 'some name'
if ((select count(1) from dbo.Table where ID = #InsertID) > 1) -- detect error; more than one record for an id
begin
insert into dbo.Error (ErrorID, ErrorDate)
select #InsertID, getdate()
end
else if not exists (select 1 from dbo.Table where ID = #InsertID) -- no record exists for ID, insert it
begin
insert into dbo.Table (ID, Name)
select #InsertID, #Name
else if exists (select 1 from dbo.Table where ID = #InsertID) -- update the single record
begin
update dbo.Table set Name = #Name where ID = #InsertID
end
A2019 returns the results of a SQL Query as a table...
You could have an if statement right after your query which checks to see if the row count of the returned table is > 0 then take action accordingly.

Insert data if it does not exist

I want to insert some data in my column only if my query parameters are not already added.
For example, if my row contains :
a=4&b=7&c=9
and now, when update happens with : b=7&c=9, then i should not append it.
o/p:a=4&b=7&c=9
But if update happens with d=9&e=9
then it should append it.
o/p : a=4&b=7&c=9&d=9&e=9
My normal Update query is :
#AdditionalParams = 'b=7&c=9'
SELECT #id = mid FROM Table2 WHERE sid = #SId
AND cid = #CId;
UPDATE Table1
SET additional_params = CONCAT (
additional_params
,iif(additional_params IS NULL, NULL, '&')
,#AdditionalParams
)
WHERE mid = #id
How can i use here the NOT EXIST Clasue.
But with not exist clause it checks whole row, I just want to check if parameters exist, then dont insert it.
I guess you are looking for a not like clause
declare #AdditionalParams varchar(50) = 'b=7&c=8'
SELECT #id = mid
FROM Table2
WHERE sid = #SId
AND cid = #CId;
UPDATE Table1
SET additional_params = CONCAT (
additional_params
,iif(additional_params IS NULL, NULL, '&')
,#AdditionalParams
)
WHERE mid = #id
and additional_params not like '%'+ #AdditionalParams +'%';

Subquery returned more than 1 value on trigger

I created a trigger to update rows in another table, triggered by a update statement in dbo.update. The reason why this trigger fails is probably because it tries to update more than 1 record. I try to change this, but without result. I'm wondering: what is the correct way to do this?
CREATE TRIGGER
[dbo].[Update]
ON
[dbo].[Records]
FOR UPDATE
AS
BEGIN
SET NOCOUNT ON
IF (SELECT State FROM INSERTED) = '1'
Begin
UPDATE dbo.Issue SET state = 1 WHERE EventID = (SELECT EventID FROM INSERTED)
DECLARE #IssueID INT
SET #issueID = (SELECT IssueID FROM Issue WHERE EventID = (SELECT EventID FROM INSERTED))
UPDATE dbo.Action SET state = 1 WHERE IssueID = #issueID
end
IF (SELECT State FROM INSERTED) = '0'
Begin
UPDATE dbo.Issue SET state = 0 WHERE EventID = (SELECT EventID FROM INSERTED)
SET #issueID = (SELECT IssueID FROM Issue WHERE EventID = (SELECT EventID FROM INSERTED))
UPDATE dbo.Action SET state = 0 WHERE IssueID = #issueID
end
END
You are correct on the diagnosis. I think you want to replace the entire if with two updates using joins to inserted:
UPDATE i
SET state = ii.state
FROM dbo.Issue i JOIN
inserted ii
ON i.EventID = ii.EventID
WHERE ii.state IN (0, 1);
UPDATE a
SET state = ii.state
FROM dbo.Action a JOIN
dbo.Issue i
ON a.EventId = i.EventId JOIN
inserted ii
ON a.IssueId = ii.IssueId
WHERE ii.state IN (0, 1);
Your update will only work when there is only one record updated. If there are multiple records updated in a batch/transaction, then INSERTED will have multiple records in it and that's when your code will error out. You can try the below query:
UPDATE dbo.Issue
SET state = INSERTED.State
FROM
INSERTED
WHERE dbo.Issue.EventId = INSERTED.EventId
AND INSERTED.State in (0, 1)
UPDATE dbo.Action
SET State = INSERTED.State
FROM
INSERTED
JOIN Issue on INSERTED.EventID = Issue.EventID
WHERE
INSERTED.State in (0,1)

How to identify the operation type(insert,update,delete) in SQL Server trigger

We are using the following trigger in SQL Server to maintain the history now I need to identify the operations just like insert,update or delete. I found some information HERE but it doesn't works with the SQL Server.
CREATE TRIGGER audit_guest_details ON [PMS].[GSDTLTBL]
FOR INSERT,UPDATE,DELETE
AS
DECLARE #SRLNUB1 INT;
DECLARE #UPDFLG1 DECIMAL(3,0);
SELECT #SRLNUB1 = I.SRLNUB FROM inserted I;
SELECT #UPDFLG1 = I.UPDFLG FROM inserted I;
BEGIN
/* Here I need to identify the operation and insert the operation type in the GUEST_ADT 3rd field */
insert into dbo.GUEST_ADT values(#SRLNUB1,#UPDFLG1,?);
PRINT 'BEFORE INSERT trigger fired.'
END;
GO
But here I need to identify the operation and want to insert operation type accordingly.
Here I don't want to create three trigger for every operations
For Inserted : Rows are in inserted only.
For Updated: Rows are in inserted and deleted.
For Deleted: Rows are in deleted only.
DECLARE #event_type varchar(42)
IF EXISTS(SELECT * FROM inserted)
IF EXISTS(SELECT * FROM deleted)
SELECT #event_type = 'update'
ELSE
SELECT #event_type = 'insert'
ELSE
IF EXISTS(SELECT * FROM deleted)
SELECT #event_type = 'delete'
ELSE
--no rows affected - cannot determine event
SELECT #event_type = 'unknown'
This is a simplified version of Mikhail's answer that uses a searched CASE expression.
DECLARE #Operation varchar(7) =
CASE WHEN EXISTS(SELECT * FROM inserted) AND EXISTS(SELECT * FROM deleted)
THEN 'Update'
WHEN EXISTS(SELECT * FROM inserted)
THEN 'Insert'
WHEN EXISTS(SELECT * FROM deleted)
THEN 'Delete'
ELSE
NULL --Unknown
END;
Since you can get multiple rows at once we do it as follows.
INSERT INTO Log_Table
(
LogDate
,LogAction
-- your field list here
,Field0
-- Example : Tracking new and old value for a specific field
-- Make sure that the [Field1_Old] is nullable or has a default value
,Field1,Field1_Old
)
SELECT
LogDate=GETDATE()
,LogAction = CASE WHEN d.[PK_Field] IS NULL THEN 'I' ELSE 'U' END
,i.Field0
,i.Field1, d.Field1
FROM inserted i
LEFT JOIN deleted d on i.[PK_Field]=d.[PK_Field]
WHERE i.[PK_Field] IS NOT NULL
INSERT INTO Log_Table
(
LogDate
,LogAction
-- your field list here
,Field0
-- Example : Tracking new and old value for a specific field
-- Make sure that the [Field1_Old] is nullable or has a default value
,Field1,Field1_Old
)
SELECT
LogDate=GETDATE()
,LogAction = 'D'
,d.Field0
,d.Field1, NULL
FROM deleted d
LEFT JOIN inserted i on i.[PK_Field]=d.[PK_Field]
WHERE i.[PK_Field] IS NULL
create trigger my_trigger on my_table
after update , delete , insert
as
declare #inserting bit
declare #deleting bit
declare #updating bit = 0
select #inserting = coalesce (max(1),0) where exists (select 1 from inserted)
select #deleting = coalesce (max(1),0) where exists (select 1 from deleted )
select #inserting = 0
, #deleting = 0
, #updating = 1
where #inserting = 1 and #deleting = 1
print 'Inserting = ' + ltrim (#inserting)
+ ', Deleting = ' + ltrim (#deleting)
+ ', Updating = ' + ltrim (#updating)
If all three are zero, there are no rows affected and I think there is no way to tell whether it is an update/delete/insert.

How do you reference new columns immediately after they are created in your SQL script

How do I need to write my SQL script to ensure my new column is visible on following lines after it is created.
This is the general form of my SQL:
BEGIN TRANSACTION
if (not exists(select 1 from THIS_TABLE))
BEGIN
ALTER TABLE THIS_TABLE add THIS_COLUMN int
END
COMMIT
BEGIN TRANSACTION
IF (NOT EXISTS (SELECT 1 FROM THIS_TABLE
WHERE THIS_COLUMN = 1))
BEGIN
UPDATE THIS_TABLE SET THIS_COLUMN = 1
END
COMMIT
This is the error I'm getting:
Invalid column name 'THIS_COLUMN'.
on this line:
IF (NOT EXISTS (SELECT 1 FROM THIS_TABLE
WHERE THIS_COLUMN = 1))
The column has to be created before a query that uses it can be parsed. You can accomplish this by putting the update in a different batch, using the "go" keyword:
alter table t1 add c1 int
go
update t1 set c1 = 1
Or by running the second transaction as dynamic SQL:
alter table t1 add c1 int
exec ('update t1 set c1 = 1')
What Andomar said is correct, you need to use the go keyword.
However, the big problem is that your logic looks wrong. Let me go through each use case:
If THIS_TABLE is not empty
If the table is not empty, the if below returns false and you will never add the new column.
if (not exists(select 1 from THIS_TABLE))
BEGIN
ALTER TABLE THIS_TABLE add THIS_COLUMN int
END
Then, the next script obviously fails, because there is no such column THIS_COLUMN:
IF (NOT EXISTS (SELECT 1 FROM THIS_TABLE
WHERE THIS_COLUMN = 1))
If THIS_TABLE is empty
If the table is empty, the column is added:
if (not exists(select 1 from THIS_TABLE))
BEGIN
ALTER TABLE THIS_TABLE add THIS_COLUMN int
END
But then the next if will always be true and the update statement will affect zero rows (because table is empty).
IF (NOT EXISTS (SELECT 1 FROM THIS_TABLE
WHERE THIS_COLUMN = 1))
BEGIN
UPDATE THIS_TABLE SET THIS_COLUMN = 1
END