/** Tests Script row by row **/
--Show Original Values
SELECT [ID]
,[ProjectID]
,[Name]
,[Languages]
FROM [dbo].[Projects] where ProjectID IN (200 , 201)
-- Insert New language for Project 200 & 201 (1 query for each row to add)
INSERT INTO ProjectLanguages (ProjectID, ISOCode, ProjectName, IsDefault)VALUES
(4205, 'PL','Test PL',0)
INSERT INTO ProjectLanguages (ProjectID, ISOCode, ProjectName, IsDefault)VALUES
(4205, 'NL','Test NL',0)
INSERT INTO ProjectLanguages (ProjectID, ISOCode, ProjectName, IsDefault)VALUES
(4206, 'PL','Test PL',0)
INSERT INTO ProjectLanguages (ProjectID, ISOCode, ProjectName, IsDefault)VALUES
(4206, 'NL','Test NL',0)
--Show Values After Insert
SELECT [ID]
,[ProjectID]
,[Name]
,[Languages]
FROM [dbo].[Projects] where ProjectID IN (200 , 201)
-- Deleted Them (1 query for each row to remove)
DELETE FROM ProjectLanguages
WHERE (ProjectID = 4205 AND ISOCode = 'PL')
DELETE FROM ProjectLanguages
WHERE (ProjectID = 4205 AND ISOCode = 'NL')
DELETE FROM ProjectLanguages
WHERE (ProjectID = 4206 AND ISOCode = 'PL')
DELETE FROM ProjectLanguages
WHERE (ProjectID = 4206 AND ISOCode = 'NL')
--Show Values After Delete
SELECT [ID]
,[ProjectID]
,[Name]
,[Languages]
FROM [dbo].[Projects] where ProjectID IN (200 , 201)
/** Tests Script Ensemblistic **/
--Show Original Values
SELECT [ID]
,[ProjectID]
,[Name]
,[Languages]
FROM [dbo].[Projects] where ProjectID IN (200 , 201)
-- Insert New 2 language for Project 200 & 201 (row 4205 & 4206 in Project Table)
INSERT INTO ProjectLanguages (ProjectID, ISOCode, ProjectName, IsDefault)VALUES
(4205, 'PL','Test',0)
INSERT INTO ProjectLanguages (ProjectID, ISOCode, ProjectName, IsDefault)VALUES
(4206, 'PL','Test',0)
INSERT INTO ProjectLanguages (ProjectID, ISOCode, ProjectName, IsDefault)VALUES
(4205, 'NL','Test NL',0)
,(4206, 'NL','Test NL',0)
--Show Values After Insert
SELECT [ID]
,[ProjectID]
,[Name]
,[Languages]
FROM [dbo].[Projects] where ProjectID IN (200 , 201)
-- Deleted Them
DELETE FROM ProjectLanguages
WHERE (ProjectID in (4205, 4206) AND (ISOCode = 'PL' OR ISOCode = 'NL'))
--Show Values After Delete
SELECT [ID]
,[ProjectID]
,[Name]
,[Languages]
FROM [dbo].[Projects] where ProjectID IN (200 , 201)
ON dbo.ProjectLanguages
AFTER INSERT, UPDATE
AS
BEGIN
DECLARE @languagesString NVARCHAR(32)
DECLARE @projectID INT
DECLARE @defaultProjectName NVARCHAR(150)
SELECT @projectID = i.ProjectID FROM inserted i
SELECT @defaultProjectName = ProjectName FROM dbo.ProjectLanguages WHERE ProjectID = @projectID and IsDefault = 1
SELECT @languagesString=
replace(replace(replace(
(
SELECT ISOCode
FROM dbo.ProjectLanguages
WHERE ProjectID = @projectID
ORDER BY isdefault DESC
FOR xml raw
)
,'"/><row ISOCode="',',')
,'<row ISOCode="','')
,'"/>','')
--as ISOList
UPDATE dbo.Projects SET
Languages = @languagesString
,Name = @defaultProjectName
WHERE
ID = @projectID
END
GO
CREATE TRIGGER RecordDeletion
ON dbo.ProjectLanguages
AFTER DELETE
AS
BEGIN
DECLARE @languagesString NVARCHAR(32)
DECLARE @projectID INT
DECLARE @defaultProjectName NVARCHAR(150)
SELECT @projectID = i.ProjectID FROM DELETED i
SELECT @defaultProjectName = ISNULL((SELECT ProjectName FROM dbo.ProjectLanguages WHERE ProjectID = @projectID and IsDefault = 1),'')
SELECT @languagesString=
replace(replace(replace(
(
SELECT ISOCode
FROM dbo.ProjectLanguages
WHERE ProjectID = @projectID
ORDER BY isdefault DESC
FOR xml raw
)
,'"/><row ISOCode="',',')
,'<row ISOCode="','')
,'"/>','')
--as ISOList
UPDATE dbo.Projects SET
Languages = @languagesString
,Name = @defaultProjectName
WHERE
ID = @projectID
END
GO
SELECT @projectID = i.ProjectID FROM inserted i
SELECT @projectID = i.ProjectID FROM DELETED i
CREATE TRIGGER ProjectLanguageSyncTrigger
ON dbo.ProjectLanguages
FOR INSERT, UPDATE, DELETE
AS
-- scenario 1
-- deleted but no insert might mean delete projects and scenario 3 might still apply
-- Not included in this example
-- scenario 2
-- insert or deleted and exists in projects s/b update projects
DECLARE @impactedProjectID TABLE (
ProjectID INT
)
--Get impacted project on UPDATE or INSERT Statement
INSERT INTO @impactedProjectID(
ProjectID
)
SELECT ProjectID
FROM (
SELECT ProjectID
FROM Inserted
group by ProjectID
UNION ALL
SELECT ProjectID
FROM Deleted
group by ProjectID
) as T
group by ProjectID
UPDATE Projects SET
Languages = (SELECT
REPLACE(REPLACE(REPLACE(
(
SELECT ProjectLanguages.ISOCode
FROM dbo.ProjectLanguages as ProjectLanguages
WHERE ProjectLanguages.ProjectID = Projects.ID
ORDER BY ProjectLanguages.isdefault DESC
FOR xml raw
)
,'"/><row ISOCode="',',')
,'<row ISOCode="','')
,'"/>',''))
,Name = ISNULL((SELECT ProjectLanguages.ProjectName
FROM dbo.ProjectLanguages as ProjectLanguages
WHERE ProjectLanguages.ProjectID = Projects.ID
AND ProjectLanguages.IsDefault = 1)
,'')
FROM dbo.Projects AS Projects
INNER JOIN @impactedProjectID as i
ON Projects.ID = i.ProjectID
-- scenario 3
-- inserted or deleted and not exists in projects s/b insert projects from projectlanguages
-- Not included in this example
GO
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (1)
Commented:
Indeed, triggers are procedural-inspired row constructors so it should be no surprise their behavior may create update anomalies as well as performance problems since the optimizer won't be able to do hashing or merging sets...
All triggers are to be replaced by declarative constraints whenever possible...
Regards...