Update a field in table when I'm updating a field in another table - sql

I have 2 tables - A and B. I have a field in Table A, which can be a null or some value; and a field in table B, which can be null or some value. Both are of nvarchar type.
Now, I would like to have a sort of event listener that whenever that field in Table A changes value, I would like the same value to be appended to the start of Table B field.
If I would want to run UPDATE statement, I would write:
UPDATE B
SET B.myValueFromB = A.myValueFromA + CONVERT(nvarchar(max),B.myValueFromB)
FROM
A JOIN B on A.Ref_num = B.Task_num
WHERE A.Ref_Num = --here is the problem
I have a form in program that updates the record having specific A.Ref_num with values. End result would be whenever I update that record, a mtaching record in Table B also gets updated. How can I do something like that?

You can use a trigger for this purpose like :
CREATE TRIGGER up_update_your_table
ON Table_A FOR UPDATE
AS
--Your id field to find the corresponding record in the other table (Table B)
DECLARE #ID VARCHAR(50)
DECLARE #Value VARCHAR(50)
SELECT #ID = YourIDFieldInTableA, #Value = YourValueFieldInTableA FROM Inserted
--Inserted returns the updated row
UPDATE Table_B SET YourValueFieldInTableB = #Value WHERE YourIDFieldInTableB = ID

Related

Creating INSTEAD OF UPDATE trigger to update HasChanged field in 3 tables

I've created a transform view that updates the master table with values from two different tables.
When doing this update, I need to change the 'HasChanged' value in all the tables for the affected records.
Ex: One row in the master table is updated with road name from one table and city name from another. The rows in the 2 tables that contained the new road name and city name must have their HasChanged value updated to 0 (from 1), as well as the master table.
For this I need to create a trigger. So far this is what I have:
CREATE TRIGGER [Transform].[trItems_HasChanged] ON [Transform].[vItems_HasChanged]
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT ON
CREATE TABLE #inserted
(
Id BIGINT
)
CREATE TABLE #PostnummerBy
(
Postnr BIGINT
)
CREATE TABLE #Vejstykke
(
Id BIGINT
)
INSERT INTO #Inserted (Infohub_Id)
SELECT Id FROM inserted
CREATE NONCLUSTERED INDEX ixInserted_Infohub_Id ON #Inserted (Infohub_Id)
UPDATE
InfohubStaging.Perfion.tMirror_Items
SET
Infohub_HasChanged = 0
FROM
InfohubStaging.Perfion.tMirror_Items
JOIN #Inserted i ON i.Infohub_Id = InfohubStaging.Perfion.tMirror_Items.Infohub_Id
WHERE
Infohub_HasChanged = 1
UPDATE
InfohubStaging.Nav.tMirror_PimItem
SET
Infohub_HasChanged = 0
FROM
InfohubStaging.Nav.tMirror_PimItem
JOIN #Inserted i ON i.Infohub_Id = InfohubStaging.Nav.tMirror_PimItem.InfohubId
WHERE
Infohub_HasChanged = 1
UPDATE
InfohubStaging.Ax.tMirror_Items_LiveUpdates
SET
Infohub_HasChanged = 0
FROM
InfohubStaging.Ax.tMirror_Items_LiveUpdates
JOIN #Inserted i ON i.Infohub_Id = InfohubStaging.Ax.tMirror_Items_LiveUpdates.Infohub_Id
WHERE
Infohub_HasChanged = 1
END
I am unsure how to correctly go about this. I'm aware that 2 temp tables are created when doing an update trigger (the data before and after). Since the temp tables are non-indexable, I need to create an index for them. So I need to create 3 tables, one for each of the tables who need to have their HasChanged value updated.
My expected output from this has the HasChanged value updated in the Vejstykke, PostnummerBy and Master table.

where condition in Insert/Update Trigger not working

This is my trigger:
Create trigger Points
on Posts
after insert, update
As
declare #Id int;
declare #value int;
select #value= Count(i.Message) from Posts i;
select #Id = [PostedBy] from inserted;
update AspNetUsers set User_points = #value * 3
where #Id = #Id
Here, at the last line, where condition always fails.Its not picking correct Id and updating same value in User_Points column in all rows not in particular rows.
I have written an insert statement to check what value i get back like this:
insert into Employee_Demo(PostedBy, TotalCount)
values (#postedby,#value );
here, i am getting correct #postedby value in table.
Previosly, i was trying this:
create trigger Points
on Posts
after insert, update
As
declare #value int
declare #postedby int
select #value= Count(Message) from Posts
select #postedby = PostedBy from inserted
update AspNetUsers set User_points = #value * 3
where Id = #postedby
please please someone help me. how to update only single row based on Id.
One more thing, PostedBy is not the primary key in post table.It is foreign key to aspnetuser table and it contains id value of user who has posted the message as u can see in below image.
tried this too:
update AspNetUsers set User_points = #value * 3
FROM INSERTED INNER JOIN Posts ON INSERTED.PostedBy = Posts.PostedBy
INNER JOIN AspNetUsers ON AspNetUsers.Id = inserted.PostedBy
Currently, you are comparing same Variable in where clause, where you are supposed to compare DB field with Variable.
Finally got it working with this query dont know how it happens
update AspNetUsers set User_points = #value * 3
where Id = (Select PostedBy from inserted)
and removing the declaration of #Id or #PostedBy. when i declared those variable and then assign value from inserted to those variable and then use that variable value in where then it was not working.
Instead, directly getting value from inserted table in where condition works.

Is there a way to make a field only editable by a trigger?

In Sql Server 2008 is there a way to set a field that it can only be changed using a Trigger?
Example:
When you create a record it is set to NULL and then updated by a trigger to e.g 1.
It should not be able to be set to anything other than NULL by the user.
And then when it is updated the trigger will set the value to 2.
create table tmp (a int primary key, b int)
GO
create trigger tr_insupd_tmp on tmp
instead of insert, update
as
if not exists(select * from deleted)
-- Process Insert
insert into tmp
select a, 1
from inserted
else
-- Process Update
update tmp
set b = 2
from tmp t
inner join inserted i on t.a = i.a
GO
Have you considered using using computed columns. If you want data in this column to be only governed by database logic then computed columns are probably way to go.

How to use trigger for update in SQL Server 2005

I have a table called tbl_gallery which has a column of datatype bit called isActive.
When the user updates the IsActive value, other rows with IsActive = true will be automatically turned to false.
How can do it with updated trigger?
Please help
I think you want something like:
CREATE TRIGGER trgGalleryActive
ON dbo.tbl_gallery
FOR UPDATE
AS
BEGIN
UPDATE g
-- Update all other gallery rows for this same user to false
SET g.IsActive = 0
FROM tbl_gallery g
INNER JOIN inserted i
on g.UserPK = i.UserPK
WHERE
-- However, we don't want current inserted records to be updated
g.TablePK <> i.TablePK
-- As per Marc's comment - don't update existing inactive rows unnecessarily
AND g.IsActive = 1
-- Only if this record is active should any of this happen
AND i.IsActive = 1
END
Trigger for update second table after updated first table :
CREATE TRIGGER update_table_cityUpdated_afterTable_cityUpdate
ON Table_city
AFTER UPDATE AS
BEGIN
DECLARE #cityId AS BIGINT
DECLARE #stateId AS BIGINT
DECLARE #CityName AS NVARCHAR(200)
SELECT #cityId=cityId FROM INSERTED
SELECT #stateId= stateId FROM INSERTED
SELECT #CityName= CityName FROM INSERTED
UPDATE table_cityUpdated
SET
[dbo].[table_cityUpdated].stateId=#stateId,
[dbo].[table_cityUpdated].CityName=#CityName
WHERE [dbo].[table_cityUpdated].cityId=#cityId
END
;

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
.....