I only use triggers as a last resort, and this isn't one of them. One technique you can use is to add a column containing a CHECKSUM() of whatever columns should not be updated, and then have a check constraint enforce a condition that the checksum value of these non-updatable columns should be equal to the value of the checksum column.
For example:
create table Customer
(
CustomerID int not null primary key,
CustomerName varchar(80) not null,
CustomerPhone varchar(80) not null,
SalesLeadID int not null,
CustomerCheckSum int not null,
constraint cc_CustomerCheckSum
check (checksum( CustomerID, SalesLeadID ) = CustomerCheckSum)
);
Supply the checksum value when inserting the table:
insert into Customer
values (32, 'John Doe', '555-555-5555', 15, CHECKSUM( 32, 15) );
The columns CustomerName and CustomerPhone can be updated.
update Customer set CustomerPhone = '555-555-1234' where CustomerID = 32;
(1 row(s) affected)
But here we see the result of attempting to update CustomerID or SalesLeadID.
update Customer set SalesLeadID = 20 where CustomerID = 32;
Msg 547, Level 16, State 0, Line 16
The UPDATE statement conflicted with the CHECK constraint "cc_CustomerCheckSum".
Of course the checksum column can also be updated, but it provides at least some degree of deterrent. If the entire record should never be updated, maybe this is a financial application, then you can populate the checksum column using a default constraint and prevent the need to supply checksum value in insert statement.
"Do not seek to follow in the footsteps of the wise. Instead, seek what they sought." - Matsuo Basho