I have this code in a trigger.
if isnull(#d_email,'') <> isnull(#i_email,'')
begin
update server2.database2.dbo.Table2
set
email = #i_email,
where user_id = (select user_id from server2.database2.dbo.Table1 where login = #login)
end
I would like to update a table on another db server, both are MSSQL. the query above works for me but it is taking over 10 seconds to complete. table2 has over 200k records. When I run the execution plan it says that the remote scan has a 99% cost.
Any help would be appreciated.
First, the obvious. Check the indexes on the linked server. If I saw this problem without the linked server issue, that would be the first thing I would check.
Suggestion:
Instead of embedding the UPDATE in the server 1 trigger, create a stored procedure on the linked server and update the records by calling the stored procedure.
Try to remove the sub-query from the UPDATE:
if isnull(#d_email,'') <> isnull(#i_email,'')
begin
update server2.database2.dbo.Table2
set email = #i_email
from server2.database2.dbo.Table2 t2
inner join
server2.database2.dbo.Table1 t1
on (t1.user_id = t2.user_id)
where t1.login = #login
end
Whoa, bad trigger! Never and I mean never, never write a trigger assuming only one record will be inserted/updated or deleted. You SHOULD NOT use variables this way in a trigger. Triggers operate on batches of data, if you assume one record, you will create integrity problems with your database.
What you need to do is join to the inserted table rather than using a varaible for the value.
Also really updating to a remote server may not be such a dandy idea in a trigger. If the remote server goes down then you can't insert anything to the orginal table. If the data can be somewaht less than real time, the normal technique is to have the trigger go to a table on the same server and then a job pick up the new info every 5-10 minutes. That way if the remote server is down, the records can still be inserted and they are stored until the job can pick them up and send them to the remote server.
Related
I am executing following UPDATE sql query against oracle database server -
UPDATE TEST.SS_USER_CREDENTIALS SET CREDENTIAL = 'UUHs4w4Nk45gHrSIHA==';
After executing this query in Oracle SQL developer, I can see spinner of execution status of query keeps spinning forever and hence no output is returned. However following SELECT query on same table returns result immediately -
SELECT * FROM TEST.SS_USER_CREDENTIALS;
Could you please help to understand why UPDATE query is not executed?
If you don't have autocommit enabled, you may need to run
COMMIT;
Otherwise oracle updates aren't actually applied to your data set
try with where clause
UPDATE TEST.SS_USER_CREDENTIALS SET CREDENTIAL = 'UUHs4w4Nk45gHrSIHA==' where id='someid';
as I see your command if the table has trillion of rows it will take time (as I guess this should not be foreign key)
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
If you are looking for a temp solution you can also change the ON UPDATE action to CASCADE and modify your ids if you got a foreign key problem
it can be you have another open uncommitted transaction for the same set of records, so they are locked for that transaction.
if you locked them, running the same UPDATE in another transaction.
Just Commit/rollback your transactions
This works for me:
Close the database connection and refresh it
Refresh the table
Restart the SQL Server in services
I know this is not a complete answer to this, hope it helped!
As far I read from this forum, its understood that there may not be any issue in a design like this. But wanted to be in the safe side.
I have a simple update query as below which has to be executed in a server (Lets say Master server):
update TempTable set [TempCol_1] = 'Value_1'
where TempTable.[ TempCol_2] = ‘Server_1’
The 'Value_1' and 'Server_1’ are variable fields. This same query has to be run from different servers.
For example, when this query is being executed from ‘server-1’ , where TempTable.[ TempCol_2] = ‘Server_1’
when this query is being executed from ‘server-2’
where TempTable.[ TempCol_2] = ‘Server_2’ and so on.
It means, even if there are concurrent updates on the same table in the master server, the where condition will remain different for each server and from each server, at a given time, there will be only one execution of the query.
While designing this scenario, should we be worried about table locks or any other lock/transaction issue on the table in the master server (i.e TempTable) ?? Will the table be open to update at the same time from different servers or will it wait for the first triggered updation to complete and makes the second triggered updation is some sort of queue or somethng??
i created a linked Mysql server on SQL server 2008 r2. i'm trying to create a trigger on sql table that automatically updates a field in the linked server table, i have a table called "QFORCHOICE" in sql that has fields "Prodcode,prodname and avqty" and a table "que_for_choie" in mysql that has fields "procode,proname and avqty"
i want the trigger to update the value of "procode" in the linked server if the value of "prodcode" in sql server changes. this is what i have so far but it has errors,
create trigger [QFORCHOICE]
ON dbo.QFORCHOICE
FOR INSERT
AS
DECLARE #prodcode numeric(18,0)
DECLARE #prodname varchar(50)
DECLARE #avqty numeric(18,0)
BEGIN
SELECT
#procode = procode,
#proname = proname,
#avqty = avqty
FROM inserted
update [LINKED_MYSQL].[que_for_choice]
SET prodname=#prodname,avqty=#avqty
WHERE prodcode = #prodcode
end
can anybody please help.
thanks in advance
1- From within a trigger, you shouldn't attempt to access anything external to the current database. It will severely slow down any insert activity, and if there are any networking issues or the remote server is down for any reason, you'll then cause the original transaction to roll back. This is rarely the right thing to do
2- you're making the reliability of your system dependent on the reliability of two servers rather than one (say they both have 99% reliability - your system that ties them together with a trigger now has 98% overall reliability).
There is SQL Server 2012 database that is used by three different applications. In that database there is a table that contains ~500k rows and for some mysterious reason this table gets emptied every now and then. I think this is possibly caused by:
A delete query without a where clause
A delete query in a loop gone wild
I am trying to locate the cause of this issue by reviewing code but no joy. I need an alternate strategy. I think I can use triggers to detect what/why all rows get deleted but I am not sure how to go about this. So:
Can I use triggers to check if a query is attempting to delete all rows?
Can I use triggers to log the problematic query and the application that issues that query?
Can I use triggers to log such actions into a text file/database table/email?
Is there a better way?
You can use Extended Events to monitor your system.
Here a simple screen shot where are.
A simple policy can monitor for delete and truncate statements.
When this events are raised details are written into file.
Here a screen with details (you can configure the script to collect more data) collected for delete statement.
Here the script used, modify the output file path
CREATE EVENT SESSION [CheckDelete] ON SERVER
ADD EVENT sqlserver.sql_statement_completed(SET collect_statement=(1)
ACTION(sqlserver.client_connection_id,sqlserver.client_hostname)
WHERE ([sqlserver].[like_i_sql_unicode_string]([statement],N'%delete%') OR [sqlserver].[like_i_sql_unicode_string]([statement],N'%truncate%')))
ADD TARGET package0.event_file(SET filename=N'C:\temp\CheckDelete.xel',max_file_size=(50))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
GO
This is a possibility that may help you. It creates a trigger on Table1 that sends an email when a process DELETEs more than 100 records. I'd modify the message to include some useful data like:
Process ID (##SPID)
Host (HOST_NAME())
Name of app (APP_NAME())
And possibly the entire query
CREATE TRIGGER Table1MassDeleteTrigger
ON dbo.Activities
FOR DELETE
AS
DECLARE #DeleteCount INT = (SELECT COUNT(*) FROM deleted)
IF(#DeleteCount > 100)
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'MailProfileName',
#recipients = 'admin#yourcompany.com',
#body = 'Something is deleting all your data!',
#subject = 'Oops!';
I have a sql script running on a server (ServerA)
This server, has a linked server set up (ServerB) - this is located off site in a datacenter.
This query works relatively speeidily:
SELECT OrderID
FROM [ServerB].[DBName].[dbo].[MyTable]
WHERE Transferred = 0
However, when updating the same table using this query:
UPDATE [ServerB].[DBName].[dbo].[MyTable]
SET Transferred = 1
It takes > 1 minute to complete (even if there's only 1 column where Transferred = 0)
Is there any reason this would be acting so slowly?
Should I have an index on MyTable for the "Transferred" column?
If you (I mean SQL server) cannot use index on remote side to select records, such remote update in fact reads all records (primary key and other needed fields) from remote side, updates these locally and sends updated records back. If your link is slow (say 10Mbit/s or less), then this scenario takes lot of time.
I've used stored procedure on remote side - this way you should only call that procedure remotely (with set of optional parameters). If your updateable subset is small, then proper indexes may help too - but stored procedure is usually faster.
UPDATE [ServerB].[DBName].[dbo].[MyTable]
SET Transferred = 1
WHERE Transferred = 0 -- missing this condition?
How often is this table being used?
If this table is used by many users at the same time, you may have a problem with lock/block.
Everytime some process updates a table without filtering the records, the entire table is locked by the transaction and the other processess that needs to update the table stand waiting.
It his case, you may be waiting for some other process to unlock the table.