Reputation: 1037
I have a TABLE (Classes_Teachers) with 3 columns (classID - INT, teacherID INT , isActive BOOLEAN).
I read the contents of a new file and create a table (StudentsTemp) with the same columns but with the latest Data and want to "merge" the two.
I can do this easily using EXCEPT AND JOIN, however this will delete any rows in Students that don't exist in StudentsTemp, however I need to be able to just set isActive to false as I have to keep the data for report purposes.
This is a "JOIN" table for a many to many relationship and so it does not have a single primary key.
So for example
STUDENTS:
+---------------------------------+ | ClassID TeacherID isActive | +---------------------------------+ | 1 2 1 | | 1 12 1 | | 1 13 0 | | 5 10 1 | +---------------------------------+
STUDENTS TEMP
+---------------------------------+ | ClassID TeacherID isActive | +---------------------------------+ | 1 2 1 | | 1 13 1 | | 1 6 1 | +---------------------------------+
In this scenario Class 5 is no longer taught by Teacher 10 and so this entry would normally be been "deleted", but I only want to change "isActive" to 0
Class 1 is also no longer taught by Teacher 12 so this should change isActive to 0.
Class 1 is now taught instead by Teacher 13; ie is now "active" so this changes isActive to 1
Finally, there is a wholly new Teacher (id = 6) who teaches classID of 1 so this inserts the row as is.
I need STUDENTS to end up like this:
+---------------------------------+ | ClassID TeacherID isActive | +---------------------------------+ | 1 2 1 | | 1 12 0 | | 1 13 1 | | 5 10 0 | | 1 6 1 | +---------------------------------+
I can do this by creating 3 temporary tables and using EXCEPT AND JOIN to populate those tables with the "deletions", "changes" and "insertions" and then running UPDATE AND INSERT on them, but I wondered if there was an easier way to do this without having to create 3 extra temporary tables.
Upvotes: 0
Views: 86
Reputation: 664
Try something like this:
MERGE Students AS T
USING Students_Temp AS S
ON (T.ClassId = S.ClassID AND T.TeacherID = S.TeacherID)
WHEN NOT MATCHED BY TARGET
THEN INSERT(ClassID, TeacherID, IsActive) VALUES(S.ClassID, S.TeacherID, S.IsActive)
WHEN NOT MATCHED BY SOURCE
THEN UPDATE SET T.IsActive = 0
WHEN MATCHED
THEN UPDATE SET T.IsActive = S.IsActive
Upvotes: 1
Reputation: 31879
First, insert new teacherID
and classID
combination. Then update rows from Students
table.
CREATE TABLE #Students(
ClassID INT,
TeachedID INT,
isActive BIT
)
CREATE TABLE #StudentsTemp(
ClassID INT,
TeachedID INT,
isActive BIT
)
INSERT INTO #Students VALUES
(1, 2, 1), (1, 12, 1), (1, 13, 0), (5, 10, 1);
INSERT INTO #StudentsTemp VALUES
(1, 2, 1), (1, 13, 1), (1, 6, 1);
UPDATE s
SET s.isActive = ISNULL(t.isActive, 0)
FROM #Students s
LEFT JOIN #StudentsTemp t
ON t.ClassID = s.ClassID
AND t.TeachedID = s.TeachedID
INSERT INTO #Students
SELECT
ClassID,
TeachedID,
isActive
FROM #StudentsTemp t
WHERE
NOT EXISTS(
SELECT 1
FROM #Students
WHERE
ClassID = t.ClassID
AND TeachedID = t.TeachedID
)
SELECT * FROM #Students
DROP TABLE #Students
DROP TABLE #StudentsTemp
RESULT
ClassID TeachedID isActive
----------- ----------- --------
1 2 1
1 12 0
1 13 1
5 10 0
1 6 1
Upvotes: 1
Reputation: 2693
Have you tried using a Merge statement?
https://msdn.microsoft.com/en-us/library/bb510625.aspx
Upvotes: 1