I want to add a trigger to my table to validate the data before allowing insert or update.
For example, something like this:
CREATE TABLE MyHorribleLegacyTable (i int IDENTITY, name char(100),
column2 char(2), column3 date, column4 int, ... column224 int)
CREATE TRIGGER ValidateLicense
ON MyHorribleLegacyTable
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
IF UserDefinedFunction(inserted) = 1
THROW 9283, 'The zinger is not configured to work with the wok', 16
IF EXISTS (SELECT * FROM inserted WHERE Name IN ('100001', 'None'))
THROW 9284, 'Invalid Licence Number', 16
INSERT INTO MyHorribleLegacyTable
SELECT * FROM inserted
END
Unfortunately, this table has an identity column, so SQL Server throws an error
An explicit value for the identity column in table 'dbo.Licences' can only be specified when a column list is used and IDENTITY_INSERT is ON.
The 'fix' is to change the INSERT
statement to explicitly list all the columns (except the identity column). But this is a maintenance nightmare.
What happens when another developer adds a column (with a constraint) into the table and does not check every trigger on the table. Any code that attempts to insert a non-default value into this new column does not work as the new column is not explicitly listed in the INSERT
statement.
Is there a better way to do the above that is maintainable?
A constraint is not possible because of the complexity.
Assuming well written code elsewhere in the system, adding the new column to the table does not break anything except the trigger code.
The 'fix' is to change the INSERT statement to explicitly list all the columns
You should be doing that anyway. It's not a maintenance nightmare at all; it's just good practice.
If you don't want to type out the column list you can use SSMS and drag the "columns" folder from the object explorer to the query window. Or generate it with a query like
select object_name(c.object_id) tn, string_agg(quotename(c.name),', ') cols
from sys.columns c
group by c.object_id