MSSQL merge with distributed transaction alternative - sql

I have a distributed transaction where I need to merge into the target remote table.
Now MERGE INTO isn't allowed according to MSDN: “target_table cannot be a remote table”.
So my workaround goes as follows: 0. begin distributed transaction 1. define a cursor 2. open it 3. if cursor has at least one record (CURSOR_STATUS()=1) fetch next 4. if exists (select top 1 * from target_remote_table where id = #myCurrentCursorId) -> when true update target_remote_table when false insert into target_remote_table 5. commit/rollback distributed transaction depending on trancount and xact_state
It works but I know that cursors are evil and you shouldn't use them. So I want to ask if there is any other way I could solve this by not using cursors?
USE [My_DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[my_proc_merge_into_remote_table]
#ID_A INT,
#ID_B INT
AS
BEGIN
SET NOCOUNT ON;
-- CURSOR VALUES
DECLARE #field_A INT
DECLARE #field_B INT
DECLARE #field_C INT
DECLARE #field_D BIT
DECLARE #field_E INT
DECLARE #field_F DATETIME
DECLARE #field_G VARCHAR(20)
DECLARE #field_H DATETIME
DECLARE #field_I VARCHAR(20)
BEGIN TRY
BEGIN DISTRIBUTED TRANSACTION
-- CURSOR !!
DECLARE my_cursor CURSOR FOR
SELECT b.field_A ,
b.field_B,
c.field_C,
a.field_D,
a.field_E,
GETDATE() AS field_F,
a.field_G,
GETDATE() AS field_H,
a.field_I
FROM dbo.source_tbl a
LEFT JOIN dbo.base_element_tbl l
ON a.obj_id = l.obj_id AND a.element_id = l.element_id
INNER JOIN dbo.base_obj_tbl b
ON a.obj_id = b.obj_id
INNER JOIN dbo.element_tbl c
ON a.element_id = c.element_id
WHERE a.ID_B = #ID_B
AND a.ID_A = #ID_A;
OPEN my_cursor;
-- check if cursor result set has at least one row
IF CURSOR_STATUS('global', 'my_cursor') = 1 BEGIN
FETCH NEXT FROM my_cursor
INTO #field_A,
#field_B,
#field_C,
#field_D,
#field_E,
#field_F,
#field_G,
#field_H,
#field_I;
WHILE ##FETCH_STATUS = 0 BEGIN
-- HINT: MY_REMOTE_TARGET_TABLE is a Synonym which already points to the correct database and table
IF EXISTS(SELECT TOP 1 * FROM MY_REMOTE_TARGET_TABLE WHERE field_A = #field_A AND field_B = #field_B AND field_C = #field_C AND field_E = #field_E)
UPDATE MY_REMOTE_TARGET_TABLE SET field_D = #field_D, field_H = #field_H, field_I = #field_I;
ELSE
INSERT INTO MY_REMOTE_TARGET_TABLE (field_A, field_B, field_C, field_D, field_E, field_F, field_G, field_H, field_I) VALUES (#field_A, #field_B, #field_C, #field_D, #field_E, #field_F, #field_G, #field_H, #field_I);
FETCH NEXT FROM my_cursor
INTO #field_A,
#field_B,
#field_C,
#field_D,
#field_E,
#field_F,
#field_G,
#field_H,
#field_I;
END;
END;
CLOSE my_cursor;
DEALLOCATE my_cursor;
IF (##TRANCOUNT > 0 AND XACT_STATE() = 1)
BEGIN
COMMIT TRANSACTION
END
END TRY
BEGIN CATCH
IF (##TRANCOUNT > 0 AND XACT_STATE() = -1)
ROLLBACK TRANSACTION
END CATCH;
END

Here you go, first inner join target and source to update, then left join to insert missing.
;WITH CTE_Source AS
(
SELECT b.field_A ,
b.field_B,
c.field_C,
a.field_D,
a.field_E,
GETDATE() AS field_F,
a.field_G,
GETDATE() AS field_H,
a.field_I
FROM dbo.source_tbl a
LEFT JOIN dbo.base_element_tbl l
ON a.obj_id = l.obj_id AND a.element_id = l.element_id
INNER JOIN dbo.base_obj_tbl b
ON a.obj_id = b.obj_id
INNER JOIN dbo.element_tbl c
ON a.element_id = c.element_id
WHERE a.ID_B = #ID_B
AND a.ID_A = #ID_A;
)
UPDATE trgt
SET trgt.field_D = src.field_D, trgt.field_H = src.field_H, trgt.field_I = src.field_I
FROM MY_REMOTE_TARGET_TABLE trgt
INNER JOIN CTE_Source src ON src.field_A = trgt.field_A AND src.field_B = trgt.field_B AND src.field_C = trgt.field_C AND src.field_E = trgt.field_E
;WITH CTE_Source AS
(
SELECT b.field_A ,
b.field_B,
c.field_C,
a.field_D,
a.field_E,
GETDATE() AS field_F,
a.field_G,
GETDATE() AS field_H,
a.field_I
FROM dbo.source_tbl a
LEFT JOIN dbo.base_element_tbl l
ON a.obj_id = l.obj_id AND a.element_id = l.element_id
INNER JOIN dbo.base_obj_tbl b
ON a.obj_id = b.obj_id
INNER JOIN dbo.element_tbl c
ON a.element_id = c.element_id
WHERE a.ID_B = #ID_B
AND a.ID_A = #ID_A;
)
INSERT INTO MY_REMOTE_TARGET_TABLE (field_A, field_B, field_C, field_D, field_E, field_F, field_G, field_H, field_I)
SELECT field_A, field_B, field_C, field_D, field_E, field_F, field_G, field_H, field_I
FROM CTE_Soure src
LEFT JOIN MY_REMOTE_TARGET_TABLE trgt ON src.field_A = trgt.field_A AND src.field_B = trgt.field_B AND src.field_C = trgt.field_C AND src.field_E = trgt.field_E
WHERE trgt.field_A IS NULL

Related

Updating table based on derived column as well as returning the resultset of the stored procedure

I have written a SQL Server stored procedure that returns a derived column in its result set. The derived column returns the difference in days and if the difference is less than 24 hours, then it returns hours.
I need to call an update statement based on value that comes from the derived column (NoOfDays) is -1: The storedprocedure would however return the entire resultset that includes the derived column and perform the update if necessary
update [org].[User]
set [Disabled] = 0
where id = #UserID AND ....
How do include this update statement to do that in this stored procedure
Stored procedure:
CREATE PROCEDURE declaration.UserAgreementsOutstanding
(#UserID INT)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
UPDATE ua
SET ua.AcceptanceWindowExpiry = GETUTCDATE() + a.ReviewPeriodInDays
FROM declaration.UserAgreement ua
INNER JOIN declaration.Agreement a ON ua.AgreementID = a.ID
WHERE ua.USERID = #UserID
AND ua.AcceptanceWindowExpiry IS NULL;
SELECT
ua.ID AS UserAgreementID,
A.ID AS AgreementID,
A.Code,
A.ComplianceCode,
A.Name, A.Description,
A.Version,
ua.UserAgreementStateID,
uas.Name AS UserAgreementStateName,
ua.AcceptanceWindowExpiry,
declaration.GetDifferenceInDaysOrHours(ua.AcceptanceWindowExpiry) AS NoOfDays,
A.Data,
pa.ID AS AuthoredByID,
pa.FirstName + ' ' + pa.LastName AS AuthoredByName,
A.Authored,
ia.ID AS IssuedByID,
ia.FirstName + ' ' + pa.LastName AS IssuedByName,
A.Issued
FROM
declaration.Agreement AS A
INNER JOIN
declaration.UserAgreement AS ua ON A.ID = ua.AgreementID
INNER JOIN
declaration.UserAgreementState AS uas ON ua.UserAgreementStateID = uas.ID
LEFT JOIN
common.Person AS pa ON A.AuthoredBy = pa.ID
LEFT JOIN
common.Person AS ia ON A.IssuedBy = ia.ID
WHERE
ua.UserID = 607
AND uas.Code IN ('ISS', 'DEF') -- Issued, Deferred
AND A.Draft = CONVERT(BIT, 0) -- Not a draft.
AND A.Deleted = CONVERT(BIT, 0) -- Not deleted.
AND (A.Issued <= GETUTCDATE() OR A.Issued IS NULL)
AND (A.Expires > GETUTCDATE() OR A.Expires IS NULL)
END TRY
BEGIN CATCH
-- do some pseudo logging
PRINT ERROR_MESSAGE();
THROW;
END CATCH;
END;
Function
CREATE FUNCTION declaration.GetDifferenceInDaysOrHours(#AcceptanceWindowExpiry datetime)
RETURNS int
AS
BEGIN
DECLARE #timeDifferenceInDays INT;
DECLARE #timeDifferenceInHours INT;
DECLARE #timeDifference INT;
SELECT #timeDifferenceInDays = DATEDIFF(d, GETUTCDATE(), #AcceptanceWindowExpiry)
IF #timeDifferenceInDays > 1
BEGIN
SELECT #timeDifference = #timeDifferenceInDays
END
ELSE
BEGIN
SELECT #timeDifferenceInHours = DATEDIFF(HOUR, GETUTCDATE(), #AcceptanceWindowExpiry)
IF #timeDifferenceInHours >= 0 AND #timeDifferenceInHours <= 24
BEGIN
SELECT #timeDifference = #timeDifferenceInHours
END
ELSE
BEGIN
SELECT #timeDifference = -1
END
END
RETURN #timeDifference;
END;
The current resultset
You can add UPDATE statement to disable the user before updating the user agreement. Also, have the transaction scope.
BEGIN TRY
BEGIN TRANSACTION;
DECLARE #OutStandingUserAgreements TABLE(UserID INT, AgreementID INT, TimeDifference INT)
INSERT INTO #OutStandingUserAgreements(UserID, AgreementID , TimeDifference)
SELECT U.Id
, UA.AgreementID
, declaration.UserAgreementsOutstanding(UA.AcceptanceWindowExpiry) AS TimeDifference
FROM [org].[User] AS U
INNER JOIN declaration.UserAgreement AS UA
ON U.UserID = UA.UserID
where U.id = #UserID;
-- We are disabling user here, based on the UserAgreement Status
UPDATE U
SET U.[Disabled] = 0
FROM [org].[User] AS U
WHERE EXISTS (SELECT 1 FROM
#OutStandingUserAgreements AS oua
WHERE oua.UserID = U.ID
AND oua.TimeDifference = -1);
UPDATE ua
SET ua.AcceptanceWindowExpiry = GETUTCDATE() + a.ReviewPeriodInDays
FROM declaration.UserAgreement ua
INNER JOIN declaration.Agreement a ON ua.AgreementID = a.ID
WHERE ua.USERID = #UserID
AND ua.AcceptanceWindowExpiry IS NULL;
IF EXISTS(SELECT 1 FROM Org.User WHERE Id = #UserID AND Disabled = 0)
BEGIN
SELECT -1;
END
ELSE
BEGIN
SELECT
ua.ID AS UserAgreementID,
A.ID AS AgreementID,
A.Code,
A.ComplianceCode,
A.Name, A.Description,
A.Version,
ua.UserAgreementStateID,
uas.Name AS UserAgreementStateName,
ua.AcceptanceWindowExpiry,
oua.TimeDifference AS NoOfDays,
A.Data,
pa.ID AS AuthoredByID,
pa.FirstName + ' ' + pa.LastName AS AuthoredByName,
A.Authored,
ia.ID AS IssuedByID,
ia.FirstName + ' ' + pa.LastName AS IssuedByName,
A.Issued
FROM
declaration.Agreement AS A
INNER JOIN
declaration.UserAgreement AS ua ON A.ID = ua.AgreementID
INNER JOIN
declaration.UserAgreementState AS uas ON ua.UserAgreementStateID = uas.ID
INNER JOIN #OutStandingUserAgreements AS oua
ON oua.AgreementID = ua.AgreementID
LEFT JOIN
common.Person AS pa ON A.AuthoredBy = pa.ID
LEFT JOIN
common.Person AS ia ON A.IssuedBy = ia.ID
WHERE
ua.UserID = 607
AND uas.Code IN ('ISS', 'DEF') -- Issued, Deferred
AND A.Draft = CONVERT(BIT, 0) -- Not a draft.
AND A.Deleted = CONVERT(BIT, 0) -- Not deleted.
AND (A.Issued <= GETUTCDATE() OR A.Issued IS NULL)
AND (A.Expires > GETUTCDATE() OR A.Expires IS NULL)
END
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH

Used Cursor inside cursor for update it is showing o rows effected, logic is working when i tried manually

stored procedure
Used Cursor inside cursor for update it is showing 0 rows effected, logic is working when i tried manually, declaring and closing done properly.
any changes do i need to do
or any alternatives than cursor.
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
ALTER PROCEDURE [dbo].[POS_Discount_Report]
#OutletId INT = NULL,
#FromDate DATE = NULL,
#ToDate DATE = NULL,
#DiscountPercent DECIMAL = NULL
AS
begin
SELECT #CutOffInvoiceAmount = AVG(InvoiceAmount) FROM POS_SalesReceiptMaster WHERE StampDate BETWEEN #FromDate AND #ToDate
DECLARE Receipt_cursor CURSOR FOR
SELECT Id FROM POS_SalesReceiptMaster WHERE StampDate BETWEEN #FromDate AND #ToDate AND InvoiceAmount <= #CutOffInvoiceAmount
OPEN Receipt_cursor
FETCH NEXT FROM Receipt_cursor
INTO #ReceiptId
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE Item_cursor CURSOR FOR
SELECT Id FROM Updated_SalesReceiptItems WHERE ReceiptId = #ReceiptId
OPEN Item_cursor
FETCH NEXT FROM Item_cursor
INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #Percentage = Percentage, #ItemPrice = Price FROM
Updated_SalesReceiptItems WHERE Id = #ID
IF #Percentage = 5
BEGIN
SELECT #UpdatePercentage = Tax5 FROM Updated_Master
Where Percentage = #DiscountPercent
END
ELSE
BEGIN
#UpdatePercentage = 5
END
UPDATE Updated_SalesReceiptItems
SET ProductId = Product.ProductId,
Actualprice = Product.Actualprice,
Quantity = Product.Qty,
ProductName = Product.ProductName,
unit = Product.unit,
CategoryName= Product.CategoryName,
Percentage= Product.Percentage,
Amount = Product.Amount FROM
(SELECT TOP 1 PM.ProductId, ProductCode,
dbo.fn_Get_ProductPrice_By_Outlet(ProductId,#OutletId)
AS
Actualprice,
(CASE WHEN ( dbo.fn_Get_ProductPrice_By_Outlet(#OutletId, ProductId) != 0)
THEN (#ItemPrice / dbo.fn_Get_ProductPrice_By_Outlet(#OutletId, ProductId))
ELSE 0
END) AS Qty,
ProductName, Unit, CategoryName, #UpdatePercentage AS Percentage,
dbo.fn_Get_ProductPrice_By_Outlet(#OutletId, ProductId) * (#UpdatePercentage/100) AS TaxAmount
FROM dbo.Products_Master PM
INNER JOIN ProductCategory_Master CM ON PM.CategoryId = CM.CategoryId
INNER JOIN tax_master TM ON PM.TaxId = TM.Id
WHERE (#ItemPrice) % nullif(dbo.fn_Get_ProductPrice_By_Outlet(#OutletId, ProductId),0) = 0
AND Percentage = #UpdatePercentage) Product
WHERE Id = #ID
end
FETCH NEXT FROM Item_cursor
INTO #ID
END
CLOSE Item_cursor;
DEALLOCATE Item_cursor;
FETCH NEXT FROM Receipt_cursor
INTO #ReceiptId
END
CLOSE Receipt_cursor;
DEALLOCATE Receipt_cursor;
END
Okay, this is pretty scrappy, and probably won't work without some fixing, but it should give you the general pattern for doing all of this in a single query?
ALTER PROCEDURE POS_Discount_Report (
#OutletId INT = NULL,
#FromDate DATE = NULL,
#ToDate DATE = NULL,
#DiscountPercent DECIMAL = NULL)
AS
BEGIN
DECLARE #CutOffInvoiceAmount NUMERIC(19,2); --?? seems to be missing from original procedure
SELECT #CutOffInvoiceAmount = AVG(InvoiceAmount) FROM POS_SalesReceiptMaster WHERE StampDate BETWEEN #FromDate AND #ToDate; --What happens if one or both of these is NULL?
--CTEs
WITH Receipt AS (
SELECT Id FROM POS_SalesReceiptMaster WHERE StampDate BETWEEN #FromDate AND #ToDate AND InvoiceAmount <= #CutOffInvoiceAmount),
Item AS (
SELECT Id FROM Updated_SalesReceiptItems s INNER JOIN Receipt r ON s.ReceiptId = r.Id),
PercentQuery AS (
SELECT i.Id, u.[Percentage], u.Price FROM Updated_SalesReceiptItems u INNER JOIN Item i ON u.Id = i.Id),
UpdatePercent AS (
SELECT p.Id, p.[Percentage], p.Price, CASE WHEN p.[Percentage] = 5 THEN u.Tax5 ELSE 5 END AS UpdatePercentage FROM PercentQuery p INNER JOIN Updated_Master u ON u.[Percentage] = #DiscountPercent)
UPDATE
u
SET
ProductId = pm.ProductId,
Actualprice = dbo.fn_Get_ProductPrice_By_Outlet(ProductId, #OutletId),
Quantity =
CASE
WHEN (dbo.fn_Get_ProductPrice_By_Outlet(#OutletId, ProductId) != 0)
THEN (#ItemPrice / dbo.fn_Get_ProductPrice_By_Outlet(#OutletId, ProductId))
ELSE 0
END,
ProductName = pm.ProductName,
unit = pm.unit, --not sure on the alias here, as it's missing in the original query
CategoryName = pm.CategoryName,
[Percentage] = u.UpdatePercentage,
Amount = dbo.fn_Get_ProductPrice_By_Outlet(#OutletId, ProductId) * (u.UpdatePercentage / 100) --although this was TaxAmount originally??!
FROM
dbo.Products_Master pm
INNER JOIN ProductCategory_Master cm ON cm.CategoryId = pm.CategoryId
INNER JOIN tax_master tm ON tm.Id = pm.TaxId
INNER JOIN UpdatePercent up ON up.Id = pm.Id
INNER JOIN Updated_SalesReceiptItems u ON u.Id = up.Id
WHERE
(p.Price) % NULLIF(dbo.fn_Get_ProductPrice_By_Outlet(#OutletId, pm.ProductId), 0) = 0
AND [Percentage] = UpdatePercentage;
END;
Basically, I use nested common-table expressions to perform the same action as your original cursors, but these are now set-based. This means I can JOIN the results to the table to be updated and perform all of the updates in a single hit.
I almost certainly got some of this wrong, as I could see a number of parts in your original query that just seemed incorrect?

Count difference between distinct and join over distinct

How do I count the number of distinct rows minus a join over those same distinct rows?
I'm writing after triggers where I need to raise an error if the user does not have rights to the rows submitted. I can do this in two statements but this seems inefficient.
DECLARE #AccessibleCount INT =
(
SELECT
COUNT(DISTINCT i.[ParentId])
FROM
inserted i
INNER JOIN [SuperSecret].[Parent] AS p ON
p.[Id] = i.[ParentId] AND
p.[LockedBy] = #UserId
);
DECLARE #ActualCount INT = (SELECT COUNT(DISTINCT [ParentId]) FROM inserted);
IF (#AccessibleCount <> #ActualCount)
BEGIN
RAISERROR(...);
ROLLBACK TRANSACTION;
END
For performance sake, it seems like I should use a subquery over the distinct inserted.ParentId for both counts. I tried the following but it resulted in "Invalid object name 'i'."
DECLARE #ActualMinusAccessible INT =
(
SELECT
COUNT(*)
-
(
SELECT
COUNT(*)
FROM
i
INNER JOIN [SuperSecret].[Parent] AS p ON
p.[Id] = i.[ParentId] AND
p.[LockedBy] = #UserId
)
FROM
(
SELECT DISTINCT [ParentId] FROM inserted
) AS i
);
IF (#ActualMinusAccessible <> 0)
BEGIN
RAISERROR (...);
ROLLBACK TRANSACTION;
END
If am not wrong you want to Raise Error if a [ParentId] is inserted which is not present in [SuperSecret].[Parent] table. Try changing your SQL query like this.
IF EXISTS (SELECT 1
FROM inserted i
WHERE NOT EXISTS (SELECT 1
FROM [SuperSecret].[Parent] a
WHERE i.[ParentId] = a.[ParentId] AND a.[LockedBy] = #UserId))
BEGIN
RAISERROR (...);
ROLLBACK TRANSACTION;
END
OR
IF (SELECT Count(DISTINCT [ParentId]) - (SELECT Count(DISTINCT i.[ParentId])
FROM inserted i
INNER JOIN [SuperSecret].[Parent] AS p
ON p.[Id] = i.[ParentId]
AND p.[LockedBy] = #UserId)
FROM inserted) <> 0
BEGIN
RAISERROR (...);
ROLLBACK TRANSACTION;
END

cursor for sql server2005

This is my cursor procedure:
DECLARE C1 CURSOR LOCAL FOR
SELECT DISTINCT
PPTR_MATCH_REF_NO,
PPTR_LDGR_CODE,
PPTR_SLMAST_ACNO,
PPTR_PPN_STATUS
FROM GLAS_PPN_TRANSACTIONS
WHERE PPTR_COMP_CODE = #COMP_CODE
AND ISNULL(PPTR_PPN_STATUS, 'X') = 'V'
DECLARE #MATCH_REF_NO NUMERIC(10,0),
#LDGR_CODE VARCHAR(MAX),
#SLMAST_ACNO VARCHAR(MAX),
#PPN_STATUS VARCHAR(2),
#ACCT_NAME VARCHAR(MAX)
BEGIN
OPEN C1
FETCH NEXT FROM C1 INTO #MATCH_REF_NO,#LDGR_CODE,#SLMAST_ACNO,#PPN_STATUS
WHILE ##FETCH_STATUS =0
BEGIN
-- SET #MATCH_REF_NO = PPTR_MATCH_REF_NO
-- SET #LDGR_CODE = PPTR_LDGR_CODE
-- SET #SLMAST_ACNO = PPTR_SLMAST_ACNO
SELECT #ACCT_NAME = COAD_PTY_FULL_NAME
FROM GLAS_SBLGR_MASTERS,
GLAS_PTY_ADDRESS
WHERE SLMA_COMP_CODE = #COMP_CODE
AND SLMA_LDGRCTL_YEAR = DBO.GLAS_VALIDATIONS_GET_OPEN_YEAR(#COMP_CODE)
AND SLMA_LDGRCTL_CODE = #LDGR_CODE
AND SLMA_STATUS = 'A'
AND SLMA_ACNO = #SLMAST_ACNO
AND COAD_COMP_CODE = SLMA_COMP_CODE
AND COAD_ADDR_ID = SLMA_ADDR_ID
IF #PPN_STATUS = 'V'
BEGIN
SELECT #PPN_STATUS = 'VER'
END
FETCH NEXT FROM C1 INTO #MATCH_REF_NO,#LDGR_CODE,#SLMAST_ACNO,#PPN_STATUS
END
CLOSE C1
END
DEALLOCATE C1
END
How can I retrive #MATCH_REF_NO, #LDGR_CODE, #SLMAST_ACNO, #PPN_STATUS and #ACCT_NAME at the same time?
here 2 select statements is there how can i combine
You can simplify this by using a common-table expression (CTE) in SQL Server 2005 - you'll get something like:
WITH Select1 AS
(
SELECT DISTINCT
PPTR_MATCH_REF_NO,
PPTR_LDGR_CODE,
PPTR_SLMAST_ACNO,
PPTR_PPN_STATUS
FROM GLAS_PPN_TRANSACTIONS
WHERE PPTR_COMP_CODE = #COMP_CODE
AND ISNULL(PPTR_PPN_STATUS, 'X') = 'V'
)
SELECT
COAD_PTY_FULL_NAME
FROM
GLAS_SBLGR_MASTERS, GLAS_PTY_ADDRESS, Select1
WHERE
SLMA_COMP_CODE = Select1.COMP_CODE
AND SLMA_LDGRCTL_YEAR = DBO.GLAS_VALIDATIONS_GET_OPEN_YEAR(Select1.COMP_CODE)
AND SLMA_LDGRCTL_CODE = Select1.LDGR_CODE
AND SLMA_STATUS = 'A'
AND SLMA_ACNO = Select1.SLMAST_ACNO
AND COAD_COMP_CODE = SLMA_COMP_CODE
AND COAD_ADDR_ID = SLMA_ADDR_ID
What I cannot determine from the code you posted is how the GLAS_SBLGR_MASTERS and the GLAS_PTY_ADDRESS are joined (on what condition). Just specifying these two in the FROM clause should be avoided - use the standard ANSI SQL JOIN statements:
FROM GLAS_SBLGR_MASTERS
INNER JOIN GLAS_PTY_ADDRESS ON ???????
Marc

Writing a complex trigger

This posting is an update (with trigger code) from my earlier posting yesterday
I am using SQL Server 2000. I am writing a trigger that is executed when a field Applicant.AppStatusRowID
Table Applicant is linked to table Location, table Company & table AppStatus.
My issue is creating the joins in my query.
When Applicant.AppStatusRowID is updated, I want to get the values from Applicant.AppStatusRowID, Applicant.FirstName, Applicant.Lastname, Location.LocNumber, Location.LocationName, Company.CompanyCode, AppStatus.DisplayText
The joins would be :
Select * from Applicant A
Inner Join AppStatus ast on ast.RowID = a.AppStatusRowID
Inner Join Location l on l.RowID = a.LocationRowID
Inner Join Company c on c.RowID = l.CompanyRowID
This is to be inserted into an Audit table (fields are ApplicantID, LastName, FirstName, Date, Time, Company, Location Number, Location Name, StatusDisposition, User)
The trigger query is:
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
CREATE TRIGGER tri_UpdateAppDispo ON dbo.Test_App
For Update
AS
declare #Approwid int
Declare #triggername sysname
Set #rowCnt = ##rowcount
Set #triggername = object_name(##procid)
If #rowCnt = 0
RETURN
If Update(appstatusrowid)
BEGIN
-----------------------------------------------------------------------------
-- insert a record to the AppDispo table, if AppstatusRowid
-- is being Updated
-----------------------------------------------------------------------------
Insert AppDispo(AppID, LastName, FirstName, [DateTime],Company,Location,LocationName,
StatusDispo,[Username])
Select d.Rowid,d.LastName, d.FirstName, getDate(),C.CompanyCode,l.locnum,l.locname, ast.Displaytext,
SUSER_SNAME()+' '+User
From deleted d with(nolock)
Inner join Test_App a with (nolock) on a.RowID = d.rowid
inner join location l with (nolock) on l.rowid = d.Locationrowid
inner join appstatus ast with (nolock) on ast.rowid = d.appstatusrowid
inner join company c with (nolock) on c.rowid = l.CompanyRowid
--Inner Join Deleted d ON a.RowID = d.RowID
--Where (a.rowid = #Approwid)
END
GO
Any ideas?
Try with this code
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
CREATE TRIGGER tri_UpdateAppDispo ON dbo.Test_App
For Update
AS
declare #Approwid int
Declare #triggername sysname
Set #rowCnt = ##rowcount
Set #triggername = object_name(##procid)
If #rowCnt = 0
RETURN
If Update(appstatusrowid)
BEGIN
-----------------------------------------------------------------------------
-- insert a record to the AppDispo table, if AppstatusRowid
-- is being Updated
-----------------------------------------------------------------------------
Insert AppDispo(AppID, LastName, FirstName, [DateTime],Company,Location,LocationName,
StatusDispo,[Username])
Select d.Rowid,d.LastName, d.FirstName, getDate(),C.CompanyCode,l.locnum,l.locname, ast.Displaytext,
SUSER_SNAME()+' '+User
From deleted d with(nolock),location l with (nolock),appstatus ast with (nolock),company c with (nolock)
where d.Locationrowid =l.rowid and
d.appstatusrowid = ast.rowid and
c.rowid = l.CompanyRowid
END GO
whith this code you get the update-deleted row(the old_value)
see you.