How to manipulate the TEXT column of DELETED/INSERTED tables in SQL Server trigger - sql-server

I have a SQL Server table and I need to code a trigger to fire when there is an update on that table.
There is a Text column in this table. I need to compare the old and new value of that column after the update, from the INSERTED and DELETED tables.
The thing is that I absolutely can't change the type of that column.
Does anyone have found a way to bypass this restriction in a SQL Server trigger ?

Instead of a trigger would it possible for you to amend your update query? Here's an example update that returns the before and after values:
-- Declare a table to hold our sample data.
DECLARE #Example TABLE
(
TextField VARCHAR(255)
)
;
-- Populate it.
INSERT INTO #Example
(
TextField
)
VALUES
('a'),
('b'),
('c')
;
-- Update the text field and view the change
UPDATE
#Example
SET
TextField = 'z'
OUTPUT
deleted.TextField AS Old_TextField,
inserted.TextField AS New_TextField
;
You could also use the INTO clause to capture this output into a new table.
For more on the INSERTED and DELETED tables see MSDN.

I decided to do something else, I don't really like it, but it allows me to use a varchar column instead of the text column. So I did this :
ALTER TABLE [MyTable]
ADD [MyVarcharColumn] AS (CONVERT([nvarchar(MAX)],[MyTextColumn]))
With this computed column, I don't need to edit any existing queries or .EDMX (Entity Framework) of an existing project, and my trigger works fine.

Related

Is there an equivalent of rowversion in SQL Server, but for a table?

I am looking for something similar to rowversion but for the whole table : a unique number automatically generated that can be used to know if table has changed.
Eg :
SELECT TABLE_VERSION('FOO')
0x00000000000007D2
INSERT INTO FOO (...) VALUES (1, 'Hello world')
SELECT TABLE_VERSION('FOO')
0x00000000000007D5
Does it exists in SQL Server ?
If not, is there any alternative ? Somethings that allow to track changes on a column would be great too.
I have been thinking of using HASHBYTES, but unfortunately it only gives hash for a single column value not for the whole column.
There is not such a thing in SQL Server, however you can implement it easly with triggers. I have used it to assist cache invalidation for web apps.
first create the table etags:
CREATE TABLE etags
(
etag_name varchar(128) NOT NULL PRIMARY KEY,
etag_value uniqueidentifier NOT NULL
)
Insert a value for the Foo table:
INSERT INTO etags VALUES ('foo', NEWID())
Then create a trigger for the foo table that updates the etag value when table changes
CREATE TRIGGER foo_etag
ON foo FOR INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON
UPDATE etags SET etag_value = NEWID()
WHERE etag_name = 'Foo'

How to dynamically exclude non-copyable fields in trigger tables

Background: I am trying to have an after update trigger which stores the changed values dynamically into another table. Since this trigger should be generic and easy to transfer to other tables and won't cause problems, if I add additional columns (If my whole code should be required to solve this, I'll update the question)
While trying to do this, I encounter following issue: I want to store the inserted table into an temporary table, which I do in this way:
SELECT *
INTO #tempINSERTED
FROM INSERTED
But the original table contains both: ntext and timestamp columns which aren't allowed in temporary tables.
Another approach I tried, was looping through the system table INFORMATION_SCHEMA.COLUMNS and build a SQL statement as a string excluding non-copyable columns, but this way I cannot access the inserted table. - I already figured I cannot access inserted if I use sp_executesql.
So my question: is there a way to access the inserted table and exclude non-copyable columns as ntext, text, image ?
Thanks in advance
You want the triggers to run fast. So the better approach would be to generate the create trigger code rather than looping through the fields in the trigger itself. Then if the table schema changes you will need to regenerate the trigger.
For your #TEMPINSERTED table you can use nvarchar(max) in place of ntext,
varchar(max) for text and varbinary(max) in place of image. You can also use and binary(8) or bigint in place of timestamp.
I would suggest using a table variable instead of an #temptable. I.e.:
declare #tempTable table (
fieldname int, -- and so on
)

Insert and initialize a SQL column with value dependent on another column data

I am completely new to writing SQL scripts and could use a little help. I need to create a script that will run only once and add a column to an existing table. This column needs to have a value directly dependent to another column's value. The value is based on whether the other column's text value contains some text.
For instance, I need a way of saying for the following value "MNA-HLTH-CAR":
if (tableValue.contains("HLTH")) {
newColumn.insert("Health"); //Insert new column value Health
} else if (tableValue.contains......
At my attempt thus far I have:
ALTER TABLE [table_name]
ADD [new_element] varchar(5)
IF
CONTAINS([column_name], "HLTH")
I probably am horrible off, and could use some help. Thanks!
If the column is always dependant, and you're using a DBMS that supports it, you can use a computed column. For SQL Server, that looks like:
alter table YourTable
add YourColumn as
(
case
when OtherColumn like '%Health%' then 'HLTH'
else 'Default'
end
)
To add a real column with values, you could use a two-step approach. After adding the column:
alter table YourTable
add YourColumn varchar(5)
Run an update query to set its value:
update YourTable
set YourColumn =
case
when OtherColumn like '%Health%' then 'HLTH'
else 'Default'
end
That should initialize the new column. But unlike the computed column, it's now up to you to maintain it.

Compute hash-value of entered value when insert or update using sql server 2008 by triggers

I have a table with two columns {FlatContent, HashedContent}. Now I want to automatically compute the hash value of FlatContent when new row was inserted or an existing row was updated. To date, I've never used from trigger, so I can't do this by trigger or another approach which is exist to solve this issue.
Thanks if anybody can help me ;)
Instead of using a trigger, make HashedContent a persisted computed column in your table definition.
ALTER TABLE YourTable
ADD HashedContent AS HashBytes('SHA1', FlatContent) PERSISTED

What's the easiest way to add automatic version information to MSSQL tables?

The information should be 2 date time columns(inserted/updated) with ms precision and should be automatically updated by the server whenever someone inserts, or updates a row.
Add columns to your table
ALTER TABLE yourTable ADD
Inserted datetime NULL,
Updated datetime NULL
GO
Create an Update and Insert Trigger to update the columns
CREATE TRIGGER yourTableInsertTrigger
ON yourTable
AFTER INSERT
AS
BEGIN
Update yourTable Set Inserted = getdate()
from Inserted
Where yourTable.Key = Inserted.Key
END
GO
CREATE TRIGGER yourTableUpdateTrigger
ON yourTable
AFTER UPDATE AS
BEGIN
Update yourTable Set Updated = getdate()
from Updated
Where yourTable.Key = Updated.Key
END
GO
Now if you want to be really clean, you'd make sure that these two columns couldn't be changed/updated by using views instead of direct table access for your other access to the data. Also if your primary keys aren't consistent, and you have many tables I'd suggest you use CodeGeneration to create the sql. MyGeneration would do nicely.
I think the inserted trigger is obsolete. Just add getdate() to the inserted column as a default value instead of null.

Resources