Trigger fire on each inserted row to insert into remote Table - sql-server

I have two different SQL 2008 servers, I don't have permission to create a linked server in any of them.
i created a trigger on server1.table1 to insert the same record to the remote server server2.table1 using OPENROWSET
i created a stored procedure to insert this record, and i have no issue when i execute the stored procedure. it insert the recored into the remote server.
the problem is when i call the stored procedure from trigger, i get an error message.
can anyone help me please to solve this issue
Stored Procedure:
USE [DB1]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter PROCEDURE [dbo].[InsertIntoRemoteTable]
#Description nvarchar(50)
AS
insert into
OPENROWSET(
'SQLNCLI', 'Server=Server2;UID=MySRV2user;PWD=MySRV2Password',
'SELECT Description FROM [RemoteDB].[dbo].[Table_1]')
SELECT #Description
Trigger:
ALTER TRIGGER [dbo].[InsertTable1]
ON [DB1].[dbo].[Table_1]
for insert
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Desc nvarchar(50)
Select #Desc = i.Descr from INSERTED i;
EXEC InsertIntoRemoteTable #Desc
END
When i try to insert a new description value in the table i got the following error message:
"No row was updated
the data in row 1 was not committed
Error source .Net SqlClient Data provider.
Error Message: the operation could not be performed because OLE DB
provider "SQLNCLI10" for linked server "(null)" returned message "The partner transaction manager has disabled its support for remote/network transaction.".
correct the errors entry or press ESC to cancel the change(s).
can anyone help please on this
thanks

I think you have over complicated this. There is really no need for a stored procedure here to do this. You can do this insert into another database directly in your trigger with a simple insert statement. This removes a ton of complexity and it is set based.
ALTER TRIGGER [dbo].[InsertTable1]
ON [DB1].[dbo].[Table_1]
for insert
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO RemoteDB].[dbo].[Table_1](Description)
Select i.Descr
from INSERTED i;
END

Related

Copy Trigger stops row being inserted

I am trying to create a trigger that copies newly inserted data from one table and inserts it into another table in a linked server.
However, when the trigger is created it stops the data appearing in the original table until the trigger is deleted and also does not even copy it over to the other table in the linked server either.
Here is my trigger
GO /****** Object: Trigger [dbo].[CopyTMSINFO] Script Date: 12/07/2022 12:53:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[CopyTMSINFO]
ON [dbo].[d_iface_att]
After INSERT
AS DECLARE #EmpID nvarchar(MAX),
#datetime datetime
SELECT #EmpID = ins.emp_id FROM INSERTED ins;
SELECT #datetime = ins.date_and_time FROM INSERTED ins;
INSERT INTO [MAL-HQ-SQL01].[MallaghanApp].[dbo].[EmployeeClockIn] (Id,Employee,TASDateTimeStart,TMSDateTime,JobType)
VALUES ( NEWID(),#EmpID,0,#datetime, 'TMS')
Any help would be greatly appreciated as i dont know much about this stuff and i am really confused.
There are two issues with your trigger:
You need to use SET NOCOUNT ON to prevent the "rows done" messing up exepcted resultsets in some client drivers.
You need to take into account multiple (or zero) rows in the inserted table.
CREATE OR ALTER TRIGGER [dbo].[CopyTMSINFO]
ON [dbo].[d_iface_att]
AFTER INSERT
AS
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM inserted)
RETURN;
INSERT INTO [MAL-HQ-SQL01].MallaghanApp.dbo.EmployeeClockIn
(Id, Employee, TASDateTimeStart, TMSDateTime, JobType)
SELECT
NEWID(),
ins.emp_id,
0,
ins.date_and_time,
'TMS'
FROM inserted ins;
However, inserting into a linked server using a trigger is very bad form anyway. What happens if the remote server is offline?
You should instead use other replication methods, such as the remote server pulling data from this server using an Agent Job.

Delete part in stored procedure not working

I have the following stored procedure in SQL Server:
CREATE PROCEDURE [dbo].[EmptyStagingTableBySupplierNr]
#suppliernumber NVARCHAR(50)
AS
BEGIN
-- routine body goes here, e.g.
-- SELECT 'Navicat for SQL Server'
INSERT INTO proclog (description)
VALUES (#suppliernumber);
DELETE FROM [dbo].[productassortment_staging]
WHERE [LieferantenNr] = #suppliernumber;
INSERT INTO proclog (description)
VALUES ('test');
END
If I execute the stored procedure directly all parts (insert, delete) work fine.
But if I execute the stored procedure from a third party software - only the insert parts are working.
I simplified the stored procedure:
CREATE PROCEDURE [dbo].[EmptyStagingTableBySupplierNr]
#suppliernumber NVARCHAR(50)
AS
BEGIN
-- routine body goes here, e.g.
-- SELECT 'Navicat for SQL Server'
INSERT INTO proclog (description)
VALUES (#suppliernumber);
DELETE FROM [dbo].[productassortment_staging]
WHERE [LieferantenNr] = '123';
INSERT INTO proclog (description)
VALUES ('test');
END
The same result: it works, if I execute it directly, but from the third party software only the insert parts are working.
I have changed the used credentials to the admin account. No change - so
a problem with insufficient rights could be excluded.
Any ideas how I can solve the problem?

OLE DB provider "SQLNCLI11" for linked server "Servername" returned message "No transaction is active."

I have a database which is on another server. I created the linked server in my mssql and inserting data on a live database by firing the trigger whenever I insert data in my local database.
I also set configurations in MSDTC from component service and restart server and client many times
But still getting this error
OLE DB provider "SQLNCLI11" for linked server "Servername" returned message >"No transaction is active.
USE HWMS
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER dbo.AshCollInsert // trigger name
ON hwms.dbo.AshCollection // local db table
AFTER INSERT AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Just INSERT everything from the [inserted] pseudotable into
--the target table
INSERT INTO [ServerName].[HWMS].dbo.AshCollection2 // server db table
(id, UserId, IncinatorId,In_Weight,IncineratorCollectTime,Barcode,flex,flag)
SELECT id, UserId, IncinatorId,In_Weight,IncineratorCollectTime,Barcode,flex,flag
FROM inserted;
END
GO

Insert stored procedure data in a temp table in SQL Server

I am trying to insert the data of a stored procedure into a temp table like below
CREATE TABLE #CustomTable3HTML
(
ItemId varchar(30),
ItemId1 varchar(30)
)
INSERT INTO #CustomTable3HTML
EXEC SalesDeals.dbo.prGetDealProposalDetail 17100102, 1
but I am getting this error
Msg 8164, Level 16, State 1, Procedure prGetDealProposalDetail, Line 138 [Batch Start Line 1]
An INSERT EXEC statement cannot be nested.
I figured this is because the stored procedure already has an insert into clause defined and I found out that it can be used only once in the calling chain.
So I started looking for other options and found out about OpenRowSet which I am using as below
SELECT *
INTO #CustomTable3HTML
FROM OPENROWSET('SQLOLEDB','Server=Demo\Demo;Trusted_Connection=Yes;Database=SalesDeals',
'SET NOCOUNT ON;SET FMTONLY OFF;EXEC SalesDeals.dbo.prGetDealProposalDetail 17100102,1')
I am getting an error when I run this SQL command
Access to the remote server is denied because no login-mapping exists.
It works fine when I use a higher level account like sysadmin but fails with the other account which is a normal db owner on the database where I am running this SQL.
There is work around of this. It's not beautiful, but it will work.
In our outer query define a table:
CREATE TABLE #CustomTable3HTML
(
ItemId varchar(30),
ItemId1 varchar(30)
)
Change the procedure adding the following code at the end:
IF OBJECT_ID('tempdb..#CustomTable3HTML')
BEGIN
INSERT INTO #CustomTable3HTML
SELECT ....
END
ELSE
BEGIN
SELECT ....
END
After executing the stored procedure you will have the data in table.

Sp to sync two tables using linked servers sql server

I'm working in a SP and I got two tables in different servers, one is the main and the other is a copy but whit less columns, all I want is to run the SP every 5 min over the main table in order to validate if new records has been created, if yes take those new records and insert them into the copy table, that resides in the other server.
Searching a solution I've found this script wich works ok in the same server, but when I try to run it with the linked server it fails....please somebody help me with this.
This is the error that a get....
OLE DB provider "SQLNCLI" for linked server "ESDBCGW001T" returned
message "The partner transaction manager has disabled its support for
remote/network transactions.". Msg 7391, Level 16, State 2, Procedure
sp_newrecords, Line 37 The operation could not be performed because
OLE DB provider "SQLNCLI" for linked server "LINKEDSERVER" was unable
to begin a distributed transaction.
All configurations are perfect, and when I run the insert without the variables runs fine,I mean, instead of #val1, #val2 and #val3 I use real values 1, 'A', 'B'.
USE [XXX]
GO
/****** Object: StoredProcedure [dbo].[sp_newrecords] Script Date: 03/02/2015 11:11:57 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <>
-- Create date: <>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[sp_newrecords]
-- Add the parameters for the stored procedure here
AS
BEGIN
DECLARE #val1 int
DECLARE #val2 nvarchar(50)
DECLARE #val3 nvarchar(50)
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE mycur1 CURSOR for
select empid,fname,lname from employee
where empid = 508 --this is for test only
OPEN mycur1
FETCH NEXT FROM mycur1 INTO #val1, #val2 , #val3
WHILE ##Fetch_Status = 0
BEGIN
begin tran /* default read committed isolation level is fine */
if not exists (select * from openquery (linkedserver,'select * from DBNAME.dbo.Employee_backup'))
--insert employee_backup values (#val1, #val2 , #val3)
begin
INSERT into [linkedserver].[DBNAME].[dbo].[Employee_backup] values (#val1, #val2 , #val3)
end
/*if not exists (select * from employee_backup with (updlock, rowlock, holdlock)
where employee_backup.empid = #val1
and employee_backup.fname = #val2 )
--insert employee_backup values (#val1, #val2 , #val3)
INSERT [LINKEDSERVER].[DBNAME].[dbo].[Employee_backup] values (#val1, #val2 , #val3)*/
--else
-- /* update */
commit /* locks are released here */
FETCH NEXT FROM mycur1 INTO #val1, #val2 , #val3`enter code here`
END
CLOSE mycur1
DEALLOCATE mycur1
END
Your database admin would need to allow that permission on the target server. Personally, I would simply replicate the table from one server to the other and then the stored procedure would run against the replicated data.
If you absolutely need to go cross server, please refer to this SO question.
why not just use replication for something like this?
Might need to enable Distributed Transaction Coordinator (DTC) for your specific problem https://technet.microsoft.com/en-us/library/cc759136%28v=ws.10%29.aspx
In addition to ensuring DTC is enabled, you should be using begin distributed tran rather than begin tran
See:
https://msdn.microsoft.com/en-us/library/ms188386.aspx

Resources