Will one trigger activate another trigger in SQL Server? - sql

There are three tables A, B, C and two triggers a, b.
When table A is updated, trigger a will be activated and update table B
When table B is updated, trigger b will be activated and update table C
When I update table A, will table C be updated?
If not, how?

DML triggers can be nested up to 32 levels, however this can be switched off at the server level. So if it is important that tables B and C are updated, then you need to be certain that this setting will never be switched off, which could be difficult to ensure for the lifetime of an application.
See MSDN > Create Nested Triggers: https://msdn.microsoft.com/en-GB/library/ms190739.aspx

Related

On a table R(ABCDE) like that, i need a SQL Trigger that prevents when tuple's A and B columns are same but try to give a different value to C

On the R(ABCDE) table tuples if A and B are same, then C also same value. I need a trigger that prevents to violate this rule when update the table.
This is too long for a comment.
This question indicates a short-coming in the data model. If C is dependent on A and B, it should have its own table. I think the data model needs to be fixed.
You should have an AB table:
AB_ID A B C
In this table the combination A/B would be unique.
Your table would then remove the three columns A, B, and C and replace them with AB_ID.
Voila! You can model the data correctly and you don't need to use a trigger.

Trigger delete on many-to-many middle table deletion

There are two tables A and B. As they have a many-to-many relation, there's also table C.
A
------
id PK
B
------
id PK
C
------
id_A PK
id_B PK
Now, a row B only exists only exists when at least one row of A has a relation to it, and one B may contain a relation to two or more different rows of A.
My question is, how do i automatically delete a row from B if there isn't any foreign to it in C? My initial though was to set a trigger, but i'm not to sure about this and i'd want a second opinion in how to proceed. Thank you.
First, one assumes that the data is initially set up correctly. That is, the only b records are the ones that meet your condition.
Then, the solution involves triggers on table c. When a row is deleted, it would check:
Does id_b have any other rows in the table?
If not, then delete the row.
This can actually be a bit tricky. In general, you don't want to query the table being triggered. So, I might suggest an alternative approach:
Add a counter on b.
Add insert/update/delete triggers on c that increments or decrements the count in b.
If the counter is 0 (or 1 before decrementing), then delete the row.
Gosh, you might find that the counter itself is sufficient, and there is no need to actually delete the row. You can get that effect if you use a view:
create view v_b as
select b.*
from b
where ab_counter > 0;
You could also create a view on b and not have to deal with triggers at all:
create view v_b as
select b.*
from b
where exists (select 1 from c where c.b_id = b.id);
#Gordon's solution above is great, However a slight modification might help.
First, one assumes that the data is initially set up correctly. That is, the only b records are the ones that meet your condition.
Then, the solution involves triggers on table c. When a row is deleted, it would check:
Does id_b have any other rows in the table?
If not, then delete the
row.
This is a bit tricky because you have to check if other rows exist. This check can be automated by using,
FOREIGN KEY(id) REFERENCES B(id) ON DELETE RESTRICT
on table C. Now you only need to delete row from B in the trigger without any checks, since the restrict constraint will automatically check if row exists in table C and restrict the delete of a referenced row in table B else delete is successful.

How to switch data from a Table A to Table B when there is no query running on Table B

i have 2 Table A, B, which have the same columns. Table B is Used for Tableau Reports. Table A is a temporary Table which has new Data from source System.
How to switch the Data from Table A to Table B when there is no Query running on Table B?
i need to do that to avoid downtime on Table B and make sure that Table B is always available for Users
Thankyou very much!
As far as I know this is something you cannot really do with straightforward methods since any RDBMS will take care of this functionality by itself. The only thing you can do is put your insert statements in a transaction block to make sure that the resulting table B will never be seen(=queried) in an "unready" (=half finished) state.
If i understand you correctly this is the scenario;
1 You load data into TableA and then the endusers use TableB
2 You want to switch data into TableB from TableA without downtime
This should solve your problem:
truncate table [dbo].[TableB] alter table [dbo].[TableA] switch to [dbo].[TableB]
This script executes within miliseconds and should be enough for your requirements. One notice though is that your TableA and TableB has to be completely the same. Same Index, same columns etc.

update data from one table to another (in a database)

DB gurus,
I am hoping someone can set set me on the right direction.
I have two tables. Table A and Table B. When the system comes up, all entries from Table A are massaged and copied over to Table B (according to Table B's schema). Table A can have tens of thousands of rows.
While the system is up, Table B is kept in sync with Table A via DB change notifications.
If the system is rebooted, or my service restarted, I want to re-initialize Table B. However, I want to do this with the least possible DB updates. Specifically, I want to:
add any rows that are in Table A, but not in Table B, and
delete any rows that are not in Table A, but are in Table B
any rows that are common to Table A and Table B should be left untouched
Now, I am not a "DB guy", so I am wondering what is conventional way of doing this.
Use exists to keep processing to a minimum.
Something along these lines, modified so the joins are correct (also verify that I didn't do something stupid and get TableA and TableB backwards from your description):
insert into TableB
select
*
from
TableA a
where
not exists (select 1 from TableB b where b.ID = a.ID)
delete from
TableB b
where
not exists (select 1 from TableA a where a.ID = b.ID)
Informix's Enterprise Replication features would do all this for you. ER works by shipping the logical logs from one server to another, and rolling them forward on the secondary.
You can configure it to be as finely-grained as you need (ie just a handful of tables).
You use the term "DB change notifications" - are you already using ER or is this some trigger-based arrangement?
If for some reason ER can't work for your configuration, I would suggest rewriting the notifications model to behave asynchronously, ie:
write notifications to a table in server 'A' that contains a timestamp or serial field
create a table on server 'B' that stores the timestamp/serial value of the last processed record
run a daemon process on server 'B' that:
compares 'A' and 'B' timestamps/serials
selects 'A' records between 'A' and 'B' timestamps
processes those records into 'B'
update 'B' timestamp/serial
sleep for appropriate time-period, and loop
So Server 'B' is responsible for ensuring its copy is in sync with 'A'. 'A' is not inconvenienced by 'B' being unavailable.
A simple way would be to use a historic table where you would put the changes from A that happened since the last update, and use that table to sync the table B instead of a direct copy from A to B. Once the sync is done, you delete the whole historic table and start anew.
What I don't understand is how table A can be update and not B if your service or computer is not running. Are they found on 2 different database or server?
Join data from both tables according to comon columns and this gives you the rows that have a match in both tables, i.e. data in A and in B. Then use this values (lets call this set M) with set operations, i.e. set minus operations to get the differences.
first requirement: A minus M
second requrement: B minus A
third requirement: M
Do you get the idea?
I am a Sql Server guy but since Sql Server 2008, for this kind of operation , a feature call MERGE is available.
By using MERGE statement we can perform insert, update and delete operations in a single statement.
So I googled and found that Informix also supports the same MERGE statement but I am not sure whether it takes care of delete too or not though insert and update is being taken care off. Moreover, this statement takes care of transaction by itself

Reconciling a column across two tables in SQL Server

There are two Databases, Database A has a table A with columns of id, group and flag. Database B has a table B with columns of ID and flag. Table B is essentially a subset of table A where the group == 'B'.
They are updated/created in odd ways that are outside my understanding at this time, and are beyond the scope of this question (this is not the time to fix the basic setup and practices of this client).
The problem is that when the flag in Table A is updated, it is not reflected in table B, but should be. This is not a time-critical problem, so it was suggested I create a job to handle this. Maybe because it's the end of the week, or maybe because I've never written more than the most basic stored procedure (I'm a programmer, not a DBA), but I'm not sure how to go about this.
At a simplistic level, the stored procedure would be something along of the lines of
Select * in table A where group == B
Then, loop through the resultset, and for each id, update the flag.
But I'm not even sure how to loop in a stored procedure like this. Suggestions? Example code would be preferred.
Complication: Alright, this gets a little harder too. For every group, Table B is in a separate database, and we need to update this flag for all groups. So, we would have to set up a separate trigger for each group to handle each DB name.
And yes, inserts to Table B are already handled - this is just to update flag status.
Assuming that ID is a unique key, and that you can use linked servers or some such to run a query across servers, this SQL statement should work (it works for two tables on the same server).
UPDATE Table_B
SET Table_B.Flag = Table_A.Flag
FROM Table_A inner join Table_B on Table_A.id = Table_B.id
(since Table_B already contains the subset of rows from Table_A where group = B, we don't have to include this condition in our query)
If you can't use linked servers, then I might try to do it with some sort of SSIS package. Or I'd use the method described in the linked question (comments, above) to get the relevant data from Database A into a temp table etc. in Database B, and then run this query using the temp table.
UPDATE
DatabaseB.dbo.Table_B
SET
DatabaseB.dbo.Table_B.[Flag] = DatabaseA.dbo.Table_A.Flag
FROM
DatabaseA.dbo.Table_A inner join DatabaseB.dbo.Table_B B
on DatabaseA.dbo.id = DatabaseB.dbo.B.id
Complication:
For sevaral groups run one such update SQL per group.
Note you can use Flag without []. I'm using the brackets only because of syntax coloring on stackoverflow.
Create an update trigger on table A that pushes the necessary changes to B as A is modified.
Basically (syntax may not be correct, I can't check it right now). I seem to recall that the inserted table contains all of the updated rows on an update, but you may want to check this to make sure. I think the trigger is the way to go, though.
create trigger update_b_trigger
on Table_A
for update
as
begin
update Table_B
set Table_B.flag = inserted.flag
from inserted
inner join Table_B
on inserted.id = Table_B.id
and inserted.group = 'B'
and inserted.flag <> Table_B.flag
end
[EDIT] I'm assuming that inserts/deletes to Table B are already handled and it's just flag updates to Table B that need to be addressed.