query: if condition in sql server update - sql

I have a SQL server table in which there are 2 columns that I want to update either of their values according to a flag sent to the stored procedure along with the new value, something like:
UPDATE
table_Name
SET
CASE
WHEN #flag = '1' THEN column_A += #new_value
WHEN #flag = '0' THEN column_B += #new_value
END AS Total
WHERE
ID = #ID
What is the correct SQL server code to do so??

I thought M.Ali's comment was correct, so I've constructed this based on his suggestion.
I'm also assuming the status field is 'approved' or 'declined' as you say based on if it's populated or not. If there are any other conditions on the status field, offcourse you must add these to you where statements
BEGIN TRANSACTION
Update Payment
set post_date = new_postdate_value
account_num = new_account_num_value
pay_am = new_pay_am_value
pay_type = new_pay_type_value
authoriz = new_authoriz_value
where status is not null
UPDATE Payment
SET account_num = new_account_num_value
WHERE status is null
COMMIT TRANSACTION

Related

Need to wait on specific column state change in SQL

I need to check for the status change of a certain column in the table
I can do it using while loop, where i can get the column value and check the value and break from the loop if value is changed.
i am using SQL server 2008.
is there a better way?
Here is the sample sql query
declare #status int = 1
select #status = status from MyTable with (nolock) where Id = 100034
while #status <> 3
begin
WAITFOR DELAY '00:01'
select #status = status from MyTable with (nolock) where Id = 100034
end
Have you considered to use a trigger instead of an stored procedure? This is exactly, what are triggers for.
CREATE TRIGGER reactOnStatus3
ON MyTable
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
IF Status = 3
EXEC DoTheMagicStoredProcedure;
END;

How do i set a variable in a store procedure to a value in another table?

im trying to create a stored procedure for my booking application that checks a status of a current holiday and from that then decides what to change the status to after a stored procedure is ran, this is my code and I am trying to draw the Status from the Holidays table but I do not know how to do with other than passing it though my html connection which wont work for other reasons.
This is my SQL store procedure up to now, if I can get the status to be drawn from the holidays table I can finish it and it will work fine: (I'm quite new to SQL as well so try not to be too complicated THANKS :) )
CREATE PROCEDURE [dbo].[spHolidayApproveOrDecline]
(
#JobRole INT,
#HolidayID INT,
#Status varchar
)
AS
BEGIN
SET #Status AS
(THIS IS WHERE I NEED TO SET
THE STATUS AS THE VALUE FROM THE HOLIDAYS TABLE!!!!)
IF #JobRole = '1003'
BEGIN
SELECT * FROM Holidays WHERE #HolidayID = Holidays.ID
IF #Status = 'Pending'
BEGIN
UPDATE Holidays
SET Status = 'ManagerAcc'
WHERE #HolidayID = Holidays.ID
AND Status = 'Pending'
END
IF #Status = 'AdminAcc'
BEGIN
UPDATE Holidays
SET Status = 'Accepted'
WHERE #HolidayID = Holidays.ID
AND Status = 'AdminAcc'
END
END
IF #JobRole = '1002'
BEGIN
SELECT * FROM Holidays WHERE #HolidayID = Holidays.ID
IF #Status = 'Pending'
BEGIN
UPDATE Holidays
SET Status = 'AdminAcc'
WHERE #HolidayID = Holidays.ID
AND Status = 'Pending'
END
IF #Status = 'ManagerAcc'
BEGIN
UPDATE Holidays
SET Status = 'Accepted'
WHERE #HolidayID = Holidays.ID
AND Status = 'ManagerAcc'
END
END
END
I think your whole procedure can be replaced by a single UPDATE:
UPDATE Holidays
SET Status = CASE
WHEN #JobRole = 1003 and Status = 'Pending' THEN 'ManagerAcc'
WHEN #JobRole = 1003 and Status = 'AdminAcc' THEN 'Accepted'
WHEN #JobRole = 1002 and Status = 'Pending' THEN 'AdminAcc'
WHEN #JobRole = 1002 and Status = 'ManagerAcc' THEN 'Accepted'
ELSE Status END
WHERE #HolidayID = Holidays.ID
If you're wanting to have #Status available to your callers, the parameter would need to be declared as OUTPUT which it currently isn't, so I won't do the extension that actually sets the #Status variable since it seems unnecessary.
In general, you should find ways in SQL to tell the system what to do, not how to do it. You shouldn't think, okay, first I'll extract the current status. Then, based on the current status and the job role, I'll apply a specific update. Tell the system what the specific conditions are and let it work out what order to do things in.
You should also be very careful whenever you specify a varchar(n) variable or column, because:
When n is not specified in a data definition or variable declaration statement, the default length is 1.
You rarely, if ever, actually want a varchar(1) variable.
When n is not specified when using the CAST and CONVERT functions, the default length is 30
This is a slightly more useful data type, but is annoying just because there doesn't seem a good reason to have different defaults for n in different contexts.

sql query - get all records based on a flag

Apologies for creating a new thread. I was not able to frame the question correctly in the previous thread.
I have a table in SQL Server 2008 that looks like this -
Id Status
--------------
1 A
2 I
3 NULL
I have a stored procedure which takes #Status as the parameter.
If the #Status is "-1", I need to retrieve records 1, 2.
If the #Status is "A", I need to retrieve only record 1.
If the #Status is "I", I need to retrieve only record 2.
I want to be able to retrieve the records in a single SELECT statement without using IF ELSE. There are a lot of joins and stuff in the SELECT statement and I don't want to repeat the same thing in the ELSE condition.
I have tried the following but get incorrect data -
SELECT * FROM Person WHERE Status = #Status OR #Status IS NOT NULL
select * from Person
where (#Status is not null and Status = #Status) or
(#Status is null and Status in ('A', 'P'))
You can do it using OR:
SELECT *
FROM Person
WHERE Status = #Status
OR (#Status = '-1' AND Status IS NOT NULL)
Of course you shouldn't use SELECT * in production code.

Whats Select '1' for in the following stored proceedure

BEGIN
IF EXISTS(SELECT * FROM Table1 WHERE ID=#ID)
BEGIN
UPDATE Table1 SET Name=#Name WHERE ID=#ID
SELECT '1'
END
ELSE
SELECT '0'
END
Is this the row no. of the table or what ?
Also "IF EXISTS" is checking what ? the table or if the ID exists or not ??
It looks like whoever wrote that Stored Procedure is using that as a return value to indicate success or failure.
Doing things that way will result in a single row with a single column being returned for each call to the procedure.
The correct way to handle this would be to actually use the return value of the stored procedure, rather than returning the single column single row:
BEGIN
IF EXISTS(SELECT * FORM Table1 WHERE ID = #ID)
BEGIN
UPDATE Table1 SET Name = #Name WHERE ID = #ID
RETURN 1
END
RETURN 0
END
The IF EXISTS is checking if there is a row in Table1 with the given ID. If there is a row it will update that row with the given name. The Select "1" will return "1" and Select "0" returns "0". The "1" or "0" would indicate if the row was found or not.
Presumably some calling code checks this value to determine if a row was updated or not.
Rather than checking and updating (two table accesses) you might as well do this.
UPDATE Table1 SET Name=#Name WHERE ID=#ID
SELECT CASE WHEN ##Rowcount = 0 THEN 0 ELSE 1 END
If id is the PK then you can just do
UPDATE Table1 SET Name=#Name WHERE ID=#ID
SELECT ##Rowcount
Note as long as SET NOCOUNT is not on then the number of rows affected will get passed back to the client application anyway.
Select '1' is used to indicate that Table1 contains the id value #ID (a parameter) was updated. Select '0' indicates that Table1 does not contain the id value #ID.

IF UPDATE() in SQL server trigger

If there's:
IF UPDATE (col1)
...in the SQL server trigger on a table, does it return true only if col1 has been changed or been updated?
I have a regular update query like
UPDATE table-name
SET col1 = 'x',
col2 = 'y'
WHERE id = 999
Now what my concern is if the "col1" was 'x' previously then again we updated it to 'x'
would IF UPDATE ("col1") trigger return True or not?
I am facing this problem as my save query is generic for all columns, but when I add this condition it returns True even if it's not changed...So I am concerned what to do in this case if I want to add condition like that?
It returns true if a column was updated. An update means that the query has SET the value of the column. Whether the previous value was the same as the new value is largely irelevant.
UPDATE table SET col = col
it's an update.
UPDATE table SET col = 99
when the col already had value 99 also it's an update.
Within the trigger, you have access to two internal tables that may help. The 'inserted' table includes the new version of each affected row, The 'deleted' table includes the original version of each row. You can compare the values in these tables to see if your field value was actually changed.
Here's a quick way to scan the rows to see if ANY column changed before deciding to run the contents of a trigger. This can be useful for example when you want to write a history record, but you don't want to do it if nothing really changed.
We use this all the time in ETL importing processes where we may re-import data but if nothing really changed in the source file we don't want to create a new history record.
CREATE TRIGGER [dbo].[TR_my_table_create_history]
ON [dbo].[my_table] FOR UPDATE AS
BEGIN
--
-- Insert the old data row if any column data changed
--
INSERT INTO [my_table_history]
SELECT d.*
FROM deleted d
INNER JOIN inserted i ON i.[id] = d.[id]
--
-- Use INTERSECT to see if anything REALLY changed
--
WHERE NOT EXISTS( SELECT i.* INTERSECT SELECT d.* )
END
Note that this particular trigger assumes that your source table (the one triggering the trigger) and the history table have identical column layouts.
What you do is check for different values in the inserted and deleted tables rather than use updated() (Don't forget to account for nulls). Or you could stop doing unneeded updates.
Trigger:
CREATE TRIGGER boo ON status2 FOR UPDATE AS
IF UPDATE (id)
BEGIN
SELECT 'DETECT';
END;
Usage:
UPDATE status2 SET name = 'K' WHERE name= 'T' --no action
UPDATE status2 SET name = 'T' ,id= 8 WHERE name= 'K' --detect
To shortcut the "No actual update" case, you need also check at the beginning whether your query affected any rows at all:
set nocount on; -- this must be the first statement!
if not exists (select 1 from inserted) and not exists (select 1 from deleted)
return;
SET NOCOUNT ON;
declare #countTemp int
select #countTemp = Count (*) from (
select City,PostCode,Street,CountryId,Address1 from Deleted
union
select City,PostCode,Street,CountryId,Address1 from Inserted
) tempTable
IF ( #countTemp > 1 )
Begin
-- Your Code goes Here
End
-- if any of these "City,PostCode,Street,CountryId,Address1" got updated then trigger
-- will work in " IF ( #countTemp > 1 ) " Code)
This worked for me
DECLARE #LongDescDirty bit = 0
Declare #old varchar(4000) = (SELECT LongDescription from deleted)
Declare #new varchar(4000) = (SELECT LongDescription from inserted)
if (#old <> #new)
BEGIN
SET #LongDescDirty = 1
END
Update table
Set LongDescUpdated = #LongDescUpdated
.....