I'm trying to insert data from one system into another so I keep an intermediate mapping table to keep the ids from old and new table.
I'm using a MERGE condition, is there any way to
DECLARE #TenantId INT = 1
MERGE dbo.[Account] AS t
USING (SELECT m.[AccountId],
m.[TenantId],
a.[ID_Account],
a.[Account_No],
a.[Account_Name],
FROM [Client1].dbo.[Account] a
LEFT JOIN migration.[Account] m ON m.[ID_Account] = a.[ID_Account] AND m.[TenantId] = #TenantId
) AS s
ON (t.[AccountId] = s.[AccountId] AND t.[TenantId] = s.[TenantId])
WHEN NOT MATCHED THEN
INSERT ([TenantId], [Number], [Name], [Active] )
VALUES (#TenantId, s.[Account_No], s.[Account_Name], 1)
OUTPUT #TenantId, inserted.[AccountId], s.[ID_Account] INTO migration.[Account];
This is fine, but if I try to run it a second time, the records are inserted again on my migration.[Account] table keeping repeated data. Is there any way to put a where condition on the output?
When you check to see if values from the source exist in the target, you check to see if the AccountId from migration.Account is equal to the AccountId from dbo.Account. You output the results to the migration table, but the original record still exists so it will be included in subsequent executions of the merge.
To fix your problem you need to either:
delete the original record
Add an isUpdated column in the migration table that you update after insertion and will prevent the source from being loaded.
Update the AccountId with the new AccountId so it will match the condition on subsequent executions.
Have the new record somehow cancel the original in the source record.
Here's a method with a new isUpdated and updates the accountId column:
UPDATE m SET
isUpdated = 1,
AccountId = o.NewAccountId
FROM migration.Account [m]
INNER JOIN (
MERGE dbo.[Account] AS t
USING (SELECT m.[AccountId],
m.[TenantId],
a.[ID_Account],
a.[Account_No],
a.[Account_Name],
FROM [Client1].dbo.[Account] a
LEFT JOIN migration.[Account] m ON m.[ID_Account] = a.[ID_Account]
AND m.[TenantId] = #TenantId
WHERE m.isUpdated IS NULL OR m.isUpdated = 0
) AS s
ON (t.[AccountId] = s.[AccountId] AND t.[TenantId] = s.[TenantId])
WHEN NOT MATCHED THEN
INSERT ([TenantId], [Number], [Name], [Active] )
VALUES (#TenantId, s.[Account_No], s.[Account_Name], 1)
OUTPUT #TenantId, s.AccountId [OriginalAccountId], inserted.[NewAccountId]
) [o] ON o.TenantId = m.TenantId AND o.OriginalAccountId = m.AccountId
What you want to do is do updates on when matched:
MERGE into dbo.[Account] AS destination
USING (SELECT m.[AccountId],
m.[TenantId],
a.[ID_Account],
a.[Account_No],
a.[Account_Name],
FROM [Client1].dbo.[Account] a
LEFT JOIN migration.[Account] m ON m.[ID_Account] = a.[ID_Account] AND m.[TenantId] = #TenantId
) AS holdinarea
ON (destination.[AccountId] = holdinarea.[AccountId] AND destination.[TenantId] = holdinarea.[TenantId])
WHEN MATCHED THEN
UPDATE set [AccountId]=holdinarea.accountid,
[TenantId]=holdinarea.tenantID
WHEN NOT MATCHED THEN
INSERT ([TenantId], [Number], [Name], [Active] )
VALUES (holdingarea.TenantId, holdingarea.[Account_No], holdingarea.[Account_Name], 1);
Related
i need insert rows on a table that comes of other, the colums in the table are empty but in te base table are full, im using a insert into select but i get: 'Error SQL: ORA-00926'
INSERT INTO TABLEROS.V_GRR_EEAF (PER_ID, EDAD, F_NACIMIENTO, CICLO_VITAL, GENERO_HOM, PERT_ETNICA, DISCAP
)A
(SELECT PER_ID, EDAD, F_NACIMIENTO, CICLO_VITAL, GENERO_HOM, PERT_ETNICA, DISCAP
FROM FUENTES.V_GRR_EEAF#CONSULTAFUENTES80 B
WHERE A.ID_BASE = B.ID_BASE
);
If I understand, you want to update empty columns in A where id_base exists in B and the updated values should be same as columns in B.
use this statement, it works:
MERGE INTO TABLEROS.V_GRR_EEAF a
USING FUENTES.V_GRR_EEAF#CONSULTAFUENTES80 b
ON(a.ID_BASE = b.ID_BASE)
WHEN MATCHED THEN
UPDATE SET
a.PER_ID = b.PER_ID,
a.EDAD = b.EDAD,
a.F_NACIMIENTO = b.F_NACIMIENTO,
a.CICLO_VITAL = b.CICLO_VITAL,
a.GENERO_HOM = b.GENERO_HOM,
a.PERT_ETNICA = b.PERT_ETNICA,
a.DISCAP = b.DISCAP;
commit;
I'm trying to update or insert one table based on the entries present in another table. But when I try to use MERGE to accomplish this. I'm getting below error message.
Error: The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.
Do I have to include more conditions in ON clause?
Code:
IF EXISTS (SELECT ShoppingCartNo FROM tbPOValidation WHERE ShoppingCartNo <> '')
BEGIN
MERGE tbPOValidation AS t
USING tbPOValidationTemp AS s
ON (CONVERT(VARCHAR(30),t.ShoppingCartNo)+CONVERT(VARCHAR(30),t.lineitemNo)+CONVERT(VARCHAR(30),t.PONo)) =
(CONVERT(VARCHAR(30),s.ShoppingCartNo)+CONVERT(VARCHAR(30),s.lineitemNo)+CONVERT(VARCHAR(30),s.PONo))
--When records are matched, update
--the records if there is any change
WHEN MATCHED AND (CONVERT(VARCHAR(30),t.ShoppingCartNo)+CONVERT(VARCHAR(30),t.lineitemNo)+CONVERT(VARCHAR(30),t.PONo)) =
(CONVERT(VARCHAR(30),s.ShoppingCartNo)+CONVERT(VARCHAR(30),s.lineitemNo)+CONVERT(VARCHAR(30),s.PONo))
THEN
UPDATE SET t.SupplierName = s.SupplierName, t.DUNS = s.DUNS, t.PONo = s.PONo, t.LineItemNo = s.LineItemNo, t.PurchDocItemDesc = s.PurchDocItemDesc,
t.POIssueDate = s.POIssueDate, t.DeliveryDate = s.DeliveryDate, t.PurchDocType = s.PurchDocType, t.MtrNo = s.MtrNo, t.Location = s.Location,
t.PayTerms = s.PayTerms, t.BlanketNo = s.BlanketNo, t.BlanketLineItemNo = s.BlanketLineItemNo, t.ShoppingCartNo = s.ShoppingCartNo,
t.SHCItmNo = s.SHCItmNo, t.ItemPricing = s.ItemPricing, t.ItmPrcCurrency = s.ItmPrcCurrency, t.Per = s.Per, t.POValue = s.POValue,
t.POValueCurrency = s.POValueCurrency, t.Qty = s.Qty, t.UOM = s.UOM, t.MFGName = s.MFGName, t.MFGPartNO = s.MFGPartNO, t.Description = s.Description,
t.Remarks = s.Remarks, t.Accept = s.Accept, t.AcceptedBy = s.Duns, t.AcceptedOn = GETDATE(), t.RejectionReason = s.RejectionReason
--When no records are matched, insert
--the incoming records from s
--table to t table
WHEN NOT MATCHED BY TARGET THEN
INSERT (SupplierName, DUNS, PONo, LineItemNo, PurchDocItemDesc, POIssueDate, DeliveryDate, PurchDocType, MtrNo,
Location, PayTerms, BlanketNo, BlanketLineItemNo, ShoppingCartNo, SHCItmNo, ItemPricing, ItmPrcCurrency, Per, POValue, POValueCurrency,
Qty, UOM, MFGName, MFGPartNO, Description, Remarks, Accept, AcceptedBy, AcceptedOn, RejectionReason)
VALUES (s.SupplierName, s.DUNS, s.PONo, s.LineItemNo, s.PurchDocItemDesc, s.POIssueDate, s.DeliveryDate, s.PurchDocType, s.MtrNo,
s.Location, s.PayTerms, s.BlanketNo, s.BlanketLineItemNo, s.ShoppingCartNo, s.SHCItmNo, s.ItemPricing, s.ItmPrcCurrency, s.Per, s.POValue,
s.POValueCurrency,s.Qty, s.UOM, s.MFGName, s.MFGPartNO, s.Description, s.Remarks, s.Accept, s.AcceptedBy, s.AcceptedOn, s.RejectionReason);
END
It is likely that the concatenation of fields is not unique i.e 10 11 12 would be equal to 101 11 2. Put special characters between the fields:
ON (CONVERT(VARCHAR(30),t.ShoppingCartNo)+'~' +CONVERT(VARCHAR(30),t.lineitemNo)+'~'+CONVERT(VARCHAR(30),t.PONo)) =
(CONVERT(VARCHAR(30),s.ShoppingCartNo)+'~' +CONVERT(VARCHAR(30),s.lineitemNo)+'~' +CONVERT(VARCHAR(30),s.PONo))
What I try to achieve is to update all data, so the new data goes into Row_ID and all other columns.
I have a table created db.test
I added new column Row_ID(integer)
This ise the first Code for inserting data to table
Insert into db.test
(
STRING0 ,
CONTACT ,
STRING2 ,
TEMPLATE,
NAME ,
EXEC_ID,
SENDDATE,
OPENDATE,
CLICKDATE
)
SELECT
acc.STRING0 ,
a.CONTACT ,
acc.STRING2 ,
a.TEMPLATE ,
a.NAME ,
a.EXEC_ID,
a.SENDDATE,
A.OPENDATE,
A.CLICKDATE
FROM db.account acc
Join db.activity a
ON acc.object_id = a.rep_contact
left JOIN db.VAL v1
ON v1.row_id = a.CAMPAIGN_TYPE
AND (v1.OBJ_FIELD_ID in(850))
left JOIN db.VAL v2
ON v2.row_id = a.CAMPAIGN_TYPE
AND (v2.OBJ_FIELD_ID in(851))
The values for ROW_ID comes from table db.VAL, but do I use update like this
Update db.test
( row_id, -- This column as integer has greated
string0,
etc...)
Select
v1.row_Id,
acc.STRING0,
etc....
Ending is the same
I tried this kind of update query, but it didn't work.
What should I change?
Because I would prefer to just update table, not drop, create new, and all new data.
NB! SQL Server ( Sybase)
As data is already inserted in the table, now you will have to update
the values in new column row_id. Following pseudo code will work
just make sure the from clause fetches the correct value of v1.row_Id:
UPDATE db.test
SET row_id = v1.row_Id
FROM db.test t1
JOIN db.account acc ON acc.STRING0 = t1.STRING0
--all match columns will go here
AND acc.STRING2 = t1.STRING2
JOIN db.activity a ON acc.[object_id] = a.rep_contact
AND a.CONTACT = t1.CONTACT
AND a.TEMPLATE = t1.TEMPLATE
AND a.NAME = t1.NAME
AND a.EXEC_ID = t1.EXEC_ID
AND a.SENDDATE = t1.SENDDATE
AND A.OPENDATE = t1.OPENDATE
AND A.CLICKDATE = t1.CLICKDATE
LEFT JOIN db.VAL v1 ON v1.row_id = a.CAMPAIGN_TYPE
AND (v1.OBJ_FIELD_ID in(850))
LEFT JOIN db.VAL v2 ON v2.row_id = a.CAMPAIGN_TYPE
AND (v2.OBJ_FIELD_ID in(851))
I posted a question at MSDN (Brazilian) site. My problem is that I want to make a select at a table that returns a first and last number (from a column) WITHOUT INTERRUPTION and WITHOUT CHANGES on other columns related on the search.
QUESTION UPDATE (2015-04-23)
I've updated my own post on MSDN as on this link. I made a SELECT that would give me almost what i want - but 1 line for the first and 1 line for the final number on each range. It is breaking perfectly, so when the Diag column is O (letter O) means that there is no other number on the range (as O stands for "Only"), so the number would be both initial and final. When the Diag column ins ´F´ is the first number of the range, and due to the ´ORDER BY´ arguments, the last number of that range (as you may guess, with an ´L´ for LAST on the Diag column) is right below it, on the next line. My task now is to create 1 more column on it and then repeated the enNumber field when Diag is O, place the next line ´enNumber´ value when the ´Diag´ column where ´F´ and eliminate all lines with ´L´ on the ´Diag´ column.
SELECT
[EnT].enPrefix,
[EnT].enNumber,
[EnT].enOrder,
[EnT].enDate,
[EnT].enNfe,
[EnT].enClient,
(CASE
WHEN [EnN].enNumber IS NULL THEN
CASE
WHEN [EnP].enNumber IS NULL THEN 'O'
ELSE 'L'
END
ELSE 'F'
END) AS [Diag]
FROM
SerialsDB.dbo.Entries AS [EnT]
LEFT OUTER JOIN SerialsDB.dbo.Entries AS [EnN]
ON ([EnT].enProduct = [EnN].enProduct) AND
([EnN].enNumber = [EnT].enNumber + 1) AND
([EnN].enOrder = [EnT].enOrder) AND
([EnN].enClient = [EnT].enClient) AND
([EnN].enNfe = [EnT].enNfe) AND
([EnN].enDate = [EnT].enDate)
LEFT OUTER JOIN SerialsDB.dbo.Entries AS [EnP]
ON ([EnT].enProduct = [EnP].enProduct) AND
([EnP].enNumber = [EnT].enNumber - 1) AND
([EnP].enOrder = [EnT].enOrder) AND
([EnP].enClient = [EnT].enClient) AND
([EnP].enNfe = [EnT].enNfe) AND
([EnP].enDate = [EnT].enDate)
WHERE
([EnT].enOrder IS NOT NULL) AND
([EnT].enClient IS NOT NULL) AND
(([EnP].enNumber IS NULL) OR
([EnN].enNumber IS NULL))
ORDER BY
[EnT].enOrder ASC,
[EnT].enDate ASC,
[EnT].enNfe ASC,
[EnT].enPrefix ASC,
[EnT].enNumber ASC
Help!
This is not going to be a simple query using a GROUP BY.
For simplicity and to show the basic idea I assume Entries table just got two columns: enNumber and enProduct. You can add all other columns and criteria later.
CREATE TABLE [Entries](
[enNumber] [int] NOT NULL,
[enProduct] [int] NOT NULL,
CONSTRAINT [PK_Entries] PRIMARY KEY CLUSTERED ([enNumber] ASC) ON [PRIMARY]
) ON [PRIMARY]
GO
INSERT INTO [Entries] VALUES (1000309,2768)
INSERT INTO [Entries] VALUES (1000310,2768)
INSERT INTO [Entries] VALUES (1000311,2768)
INSERT INTO [Entries] VALUES (1000312,2768)
INSERT INTO [Entries] VALUES (1000313,2768)
INSERT INTO [Entries] VALUES (1000314,2768)
INSERT INTO [Entries] VALUES (1000315,2768)
INSERT INTO [Entries] VALUES (1000316,2768)
INSERT INTO [Entries] VALUES (1000317,2768)
/* interrupt */
INSERT INTO [Entries] VALUES (1001388,3328)
INSERT INTO [Entries] VALUES (1001389,3328)
INSERT INTO [Entries] VALUES (1001390,3328)
INSERT INTO [Entries] VALUES (1001391,3328)
INSERT INTO [Entries] VALUES (1001392,3328)
/* change */
INSERT INTO [Entries] VALUES (1001393,3743)
INSERT INTO [Entries] VALUES (1001394,3743)
INSERT INTO [Entries] VALUES (1001395,3743)
INSERT INTO [Entries] VALUES (1001396,3743)
/* change */
INSERT INTO [Entries] VALUES (1001397,3328)
INSERT INTO [Entries] VALUES (1001398,3328)
INSERT INTO [Entries] VALUES (1001399,3328)
INSERT INTO [Entries] VALUES (1001400,3328)
/* interrupt */
INSERT INTO [Entries] VALUES (1003000,2768)
/* change */
INSERT INTO [Entries] VALUES (1003001,3328)
INSERT INTO [Entries] VALUES (1003002,3328)
INSERT INTO [Entries] VALUES (1003003,3328)
GO
Create two views, one of them giving all the records that act as the initial of a group and another view for the finals.
A record is an initial/final record if the previous/next enNumber does not exist (an interrupt) or has different values (a change).
CREATE VIEW [Initials] AS
SELECT E.enNumber
FROM Entries E
LEFT JOIN Entries E2 on E2.enNumber = E.enNumber - 1
AND E2.enProduct= E.enProduct
WHERE E2.enNumber IS NULL
GO
CREATE VIEW [Finals] AS
SELECT E.enNumber
FROM Entries E
LEFT JOIN Entries E2 on E2.enNumber = E.enNumber + 1
AND E2.enProduct= E.enProduct
WHERE E2.enNumber IS NULL
GO
Each record in Initials has a counterpart in Finals with an enNumber equal or greater than its enNumber.
SELECT i.enNumber AS Initial, E.enProduct
FROM Initials i
LEFT JOIN Entries E ON E.enNumber = i.enNumber
SELECT f.enNumber AS Final, E.enProduct
FROM Finals f
LEFT JOIN Entries E ON E.enNumber = f.enNumber
Initial enProduct
1000309 2768
1001388 3328
1001393 3743
1001397 3328
1003000 2768
1003001 3328
Final enProduct
1000317 2768
1001392 3328
1001396 3743
1001400 3328
1003000 2768
1003003 3328
You can combine these two views in different ways to achieve the desired results:
SELECT i.enNumber AS initial, MIN(f.enNumber) AS final, E.enProduct
FROM Initials i
LEFT JOIN finals f ON f.enNumber >= i.enNumber
LEFT JOIN Entries E ON E.enNumber = i.enNumber
GROUP BY i.enNumber, E.enProduct
ORDER BY i.enNumber
initial final enProduct
1000309 1000317 2768
1001388 1001392 3328
1001393 1001396 3743
1001397 1001400 3328
1003000 1003000 2768
1003001 1003003 3328
I think you need to do this with subquery. In the subquery, you will get the min and max values and include the columns you want to sort by. In the main query, you will select all columns. See the following link for details:
http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
Section "Selecting the one maximum row from each group"
I've wrote a query and got the results i was trying to find. I still don't like it very much as i think it will have a big cost on the database to run it, and i'd like to find one simpler. But anyway, the "problem" it self is resolved.
The resulting query is writen as follows:
SELECT
[Pre].[pfPrefix],
[Pro].[prId],
[Pro].[prName],
(CASE
WHEN [EnP].[enNumber] IS NULL THEN [EnT].[enNumber]
ELSE
(SELECT TOP 1
[iET].[enNumber]
FROM
[SerialsDB].[dbo].[Entries] AS [iET]
LEFT OUTER JOIN [SerialsDB].[dbo].[Entries] AS [iEP]
ON (([iEP].[enProduct] IS NULL AND [iET].[enProduct] IS NULL) OR
([iEP].[enProduct] = [iET].[enProduct])) AND
(([iEP].[enOrder] IS NULL AND [iET].[enOrder] IS NULL) OR
([iEP].[enOrder] = [iET].[enOrder])) AND
(([iEP].[enClient] IS NULL AND [iET].[enClient] IS NULL) OR
([iEP].[enClient] = [iET].[enClient])) AND
(([iEP].[enNfe] IS NULL AND [iET].[enNfe] IS NULL) OR
([iEP].[enNfe] = [iET].[enNfe])) AND
(([iEP].[enDate] IS NULL AND [iET].[enDate] IS NULL) OR
([iEP].[enDate] = [iET].[enDate])) AND
(([iEP].[enAuth] IS NULL AND [iET].[enAuth] IS NULL) OR
([iEP].[enAuth] = [iET].[enAuth])) AND
(([iEP].[enStatus] IS NULL AND [iET].[enStatus] IS NULL) OR
([iEP].[enStatus] = [iET].[enStatus])) AND
([iEP].[enNumber] = ([iET].[enNumber] - 1))
WHERE
(([iET].[enProduct] IS NULL AND [EnT].[enProduct] IS NULL) OR
([iET].[enProduct] = [EnT].[enProduct])) AND
(([iET].[enOrder] IS NULL AND [EnT].[enOrder] IS NULL) OR
([iET].[enOrder] = [EnT].[enOrder])) AND
(([iET].[enDate] IS NULL AND [EnT].[enDate] IS NULL) OR
([iET].[enDate] = [EnT].[enDate])) AND
(([iET].[enClient] IS NULL AND [EnT].[enClient] IS NULL) OR
([iET].[enClient] = [EnT].[enClient])) AND
(([iET].[enNfe] IS NULL AND [EnT].[enNfe] IS NULL) OR
([iET].[enNfe] = [EnT].[enNfe])) AND
(([iET].[enAuth] IS NULL AND [EnT].[enAuth] IS NULL) OR
([iET].[enAuth] = [EnT].[enAuth])) AND
(([iET].[enStatus] IS NULL AND [EnT].[enStatus] IS NULL) OR
([iET].[enStatus] = [EnT].[enStatus])) AND
([iET].[enNumber] <= [EnP].[enNumber]) AND
([iEP].[enNumber] IS NULL)
ORDER BY
[iET].[enNumber] DESC)
END) AS [Initial],
[EnT].[enNumber] AS [Final],
[EnT].[enOrder],
[EnT].[enDate],
[EnT].[enNfe],
[EnT].[enClient],
[Cli].[clGroup],
[EnT].[enAuth]
FROM
[SerialsDB].[dbo].Entries AS [EnT]
LEFT OUTER JOIN [SerialsDB].[dbo].[Entries] AS [EnN]
ON ([EnN].[enProduct] = [EnT].[enProduct]) AND
([EnN].[enOrder] = [EnT].[enOrder]) AND
([EnN].[enClient] = [EnT].[enClient]) AND
(([EnN].[enNfe] IS NULL AND [EnT].[enNfe] IS NULL) OR
([EnN].[enNfe] = [EnT].[enNfe])) AND
([EnN].[enDate] = [EnT].[enDate]) AND
([EnN].[enStatus] = [EnT].[enStatus]) AND
([EnN].[enAuth] = [EnT].[enAuth]) AND
([EnN].[enNumber] = ([EnT].[enNumber] + 1))
LEFT OUTER JOIN [SerialsDB].[dbo].[Entries] AS [EnP]
ON ([EnP].[enProduct] = [EnT].[enProduct]) AND
([EnP].[enOrder] = [EnT].[enOrder]) AND
([EnP].[enClient] = [EnT].[enClient]) AND
(([EnP].[enNfe] IS NULL AND [EnT].[enNfe] IS NULL) OR
([EnP].[enNfe] = [EnT].[enNfe])) AND
([EnP].[enDate] = [EnT].[enDate]) AND
([EnP].[enStatus] = [EnT].[enStatus]) AND
([EnP].[enAuth] = [EnT].[enAuth]) AND
([EnP].[enNumber] = ([EnT].[enNumber] - 1))
LEFT OUTER JOIN [SerialsDB].[dbo].[Prefixes] AS [Pre]
ON ([EnT].[enPrefix] = [Pre].[pfId])
LEFT OUTER JOIN [SerialsDB].[dbo].[Products] AS [Pro]
ON ([EnT].[enProduct] = [Pro].[prId])
LEFT OUTER JOIN [SerialsDB].[dbo].[Clients] AS [Cli]
ON ([EnT].[enClient] = [Cli].[clId])
WHERE
([EnT].[enOrder] IS NOT NULL) AND
([EnT].[enClient] IS NOT NULL) AND
([EnN].[enNumber] IS NULL) AND
([EnT].[enStatus] = 4) AND
([EnT].[enAuth] IS NOT NULL)
Thank you Amir for the great inputs, and for Stamen for the suggestion.
INSERT INTO AutomatedTest_XMLReconciliation(TaskID, TestCaseID, TestInstanceID, XMLHierarchyLevelID, XMLNode, XMLValue_Truth, XMLValue_Test)
(
(SELECT A.TaskID, A.TestCaseID, NULL, A.XMLHierarchyLevelID, A.XMLNode, A.XMLValue_Truth, NULL
FROM AutomatedTest_XMLTruthData A
LEFT JOIN AutomatedTest_Auth B
ON A.TestCaseID = B.TestCaseID
FULL Join AutomatedTest_XMLTestData C
ON B.TestInstanceID = C.TestInstanceID AND A.TruthIdentity = C.TestIdentity AND A.XMLHierarchyLevelID = C.XMLHierarchyLevelID AND A.XMLNode = C.XMLNode AND A.TaskID = C.TaskID
WHERE (B.ReconcileDate IS NULL AND A.TaskID IS NOT NULL)
EXCEPT
(Select A.TaskID, A.TestCaseID, NULL, A.XMLHierarchyLevelID, A.XMLNode, A.XMLValue_Truth, NULL
FROM AutomatedTest_XMLTruthData A
INNER JOIN AutomatedTest_Auth B
ON A.TestCaseID = B.TestCaseID
INNER JOIN AutomatedTest_XMLTestData C
ON B.TestInstanceID = C.TestInstanceID AND A.TruthIdentity = C.TestIdentity AND A.XMLHierarchyLevelID = C.XMLHierarchyLevelID AND A.XMLNode = C.XMLNode AND A.TaskID = C.TaskID)
)
UNION
(SELECT C.TaskID, NULL, C.TestInstanceID, C.XMLHierarchyLevelID, C.XMLNode, NULL, C.XMLValue_Test
FROM AutomatedTest_XMLTruthData A
LEFT JOIN AutomatedTest_Auth B
ON A.TestCaseID = B.TestCaseID
FULL JOIN AutomatedTest_XMLTestData C
ON B.TestInstanceID = C.TestInstanceID AND A.TruthIdentity = C.TestIdentity AND A.XMLHierarchyLevelID = C.XMLHierarchyLevelID AND A.XMLNode = C.XMLNode AND A.TaskID = C.TaskID
WHERE B.ReconcileDate IS NULL AND C.TaskID IS NOT NULL)
EXCEPT
(Select C.TaskID, NULL, C.TestInstanceID, C.XMLHierarchyLevelID, C.XMLNode, NULL, C.XMLValue_Test
FROM AutomatedTest_XMLTruthData A
INNER JOIN AutomatedTest_Auth B
ON A.TestCaseID = B.TestCaseID
INNER JOIN AutomatedTest_XMLTestData C
ON B.TestInstanceID = C.TestInstanceID AND A.TruthIdentity = C.TestIdentity AND A.XMLHierarchyLevelID = C.XMLHierarchyLevelID AND A.XMLNode = C.XMLNode AND A.TaskID = C.TaskID)
))
UPDATE AutomatedTest_Auth
SET ReconcileDate = GETDATE()
WHERE (TestCaseID IN (Select TestCaseID FROM AutomatedTest_DataReconciliation WHERE TestCaseID IS NOT NULL)
OR TestInstanceID IN (Select TestInstanceID FROM AutomatedTest_DataReconciliation WHERE TestInstanceID IS NOT NULL))
AND ReconcileDate IS NULL
So I've got this insert query that is meant to check two tables, one test and one auth, and compare their rows. It matches a TestInstance in the test table with a TestCase in a truth table through the AutomatedTest_Auth table.
Once it is done, it updates the AutomatedTest_Auth table with the GETDATE() stamp to show that the reconciliation process is complete. The insert checks this in the WHEREs to make sure that it does not insert anything that is already inserted by making sure the ReconcileDate IS NULL (it defaults to null on upon a new entry into the AutomatedTest_Auth table).
My problem, however, is that the second "B.Reconcile IS NULL" is not working. Upon running this twice, it will pick up the same rows from AutomatedTest_XMLTestData it picked up the first time and insert them again. (Just a note, there is no PK violation, as the Reconciliation columns could overlap at any time; it has an identity column instead).
Is this an order of operations issue? ... a bug? Any help would be nice.
Also, when I change the B.ReconcileDate IS NULL to IS NOT NULL, the insert swaps, and it will instead insert the same rows from AutomatedTest_XMLTruthData and not AutomatedTest_XMLTestData, so I know the inserts from AutomatedTest_XMLTruthData are correctly recognizing the WHERE clause, and that AutomatedTest_XMLTestData is incorrectly inverting the B.ReconcileData IS NULL to IS NOT NULL.
You are inserting into a table called AutomatedTest_XMLReconciliation
The update where condition looks at a table called AutomatedTest_DataReconciliation which is not referenced elsewhere in your script. Is this correct? I think the Update should be:
UPDATE AUTOMATEDTEST_AUTH
SET RECONCILEDATE = GETDATE()
WHERE ( TESTCASEID IN (SELECT TESTCASEID
FROM AUTOMATEDTEST_XMLRECONCILIATION
WHERE TESTCASEID IS NOT NULL)
OR TESTINSTANCEID IN (SELECT TESTINSTANCEID
FROM AUTOMATEDTEST_XMLRECONCILIATION
WHERE TESTINSTANCEID IS NOT NULL) )
AND RECONCILEDATE IS NULL