Reputation: 1
I would like to stop an update query if the value of a column trying to be updated is different than what it is trying to be updated to. I have this trigger:
create trigger dbo.NoUpdate
on HistoricalValues With Encryption
for update
as
if update (value)
begin
rollback transaction
end
But I would like to add something like this (pseudo code):
if update(value) and oldValue != newValue
rollback transaction
Where oldValue
is the value currently in the row and new value is the proposed value from the update statement.
This has to work with SQL Server 2014 Express at a minimum.
Upvotes: 0
Views: 1058
Reputation: 96015
To expand on my comment "If you don't want people to UPDATE
a specific column, wouldn't you be better off with a permissions based approach?", personally I would do something like this:
CREATE TABLE dbo.YourTable (id int IDENTITY,
GoodColumn varchar(10),
BadColumn varchar(10));
GO
CREATE USER TestUser WITHOUT LOGIN;
GO
GRANT SELECT, UPDATE, DELETE, INSERT ON dbo.YourTable TO TestUser;
GO
DENY UPDATE ON dbo.YourTable(BadColumn) TO TestUser;
GO
INSERT INTO dbo.YourTable (GoodColumn,
BadColumn)
VALUES('test123','example12'),
('test456','example34');
GO
EXECUTE AS USER = 'TestUser';
GO
UPDATE dbo.YourTable
SET GoodColumn = 'Test789'
WHERE BadColumn = 'example34';
GO
UPDATE dbo.YourTable
SET BadColumn = 'Example56'
WHERE GoodColumn = 'test123';
GO
REVERT;
GO
SELECT *
FROM dbo.YourTable;
GO
DROP TABLE dbo.YourTable;
GO
DROP USER TestUser;
If, for some reason, you must use a TRIGGER
, you could do something like this, however, I still suggest the permissions approach:
CREATE TRIGGER dbo.NoUpdateBad ON dbo.YourTable
AFTER UPDATE
AS
IF EXISTS (SELECT 1
FROM Inserted i
JOIN deleted d ON i.id = d.id
WHERE d.BadColumn != i.BadColumn
OR (d.BadColumn IS NULL AND i.BadColumn IS NOT NULL)
OR (d.BadColumn IS NOT NULL AND i.BadColumn IS NULL))
THROW 51000, N'Cannot change the value of the column "BadColumn".',1;
GO
UPDATE dbo.YourTable
SET BadColumn = 'asdjk'
WHERE id = 2;
GO
UPDATE dbo.YourTable
SET BadColumn = NULL
WHERE id = 1;
GO
SELECT *
FROM dbo.YourTable;
As I mention, however, neither of these will stop an sa
account. DENY
is ignored by sysadmin
privileged accounts, and an sa
would easily be able to disable to above trigger; even if you gave them a hurdle to jump first. it's much like thinking that turning xp_cmdshell
well stop someone with access to an sa
account. It doesn't, it's just a 1 second bump in the road to them, as they're just enable it.
Upvotes: 1