Search code examples
sqldynamiccursor

Sql: Query returns column name instead of Value


I have structure like this to use a Dynamic column name in After Update trigger

this two query returns ColumnName instead of Value by this statement,

(select @Name from deleted)
(select @Name from inserted)

How can i get the value from this and then store into variable?

ALTER TRIGGER [dbo].[afterUpdate_Project] ON [dbo].[Projects]
FOR UPDATE 
as 
begin

SET NOCOUNT ON;

DECLARE @ModifiedBy int = (select IsNULL(LastModifiedBy,0) from inserted)


 DECLARE @Name varchar(MAX)
 DECLARE my_Cursor CURSOR FOR 
 (
    select C.name from sys.tables T
    inner join sys.columns C on
    T.object_id = C.object_id
    where T.name = 'Projects'
 )

 OPEN my_Cursor; 

 FETCH NEXT FROM my_Cursor into @Name;

    WHILE @@FETCH_STATUS = 0 
    BEGIN
        DECLARE @OldValue nvarchar(MAX) = (select @Name from deleted)
        DECLARE @NewValue nvarchar(MAX) = (select @Name from inserted)
        print  @OldValue
        print  @NewValue

            If (@OldValue <> @NewValue)
                BEGIN
                    insert into EntityHistory 
                    values(1, @Name, @OldValue, @NewValue, @ModifiedBy, GETDATE())  
                END

    FETCH NEXT FROM my_Cursor into @Name;
    END

 CLOSE my_Cursor; DEALLOCATE my_Cursor;
 END

Solution

  • Finally I as able to find a solution for your problem. It involves temp tables. Using temp tables excessively is not recommended but I could not figure out better solution than that.

    Following is the ALTER TRIGGER script I created and it worked perfectly for my table.

    ALTER TRIGGER [dbo].[afterUpdate_Project] ON [dbo].[Projects]
    FOR UPDATE 
    AS 
    BEGIN
    
        SET NOCOUNT ON;
    
        DECLARE @ModifiedBy NVARCHAR(255) = (SELECT IsNULL(UserId,0) FROM inserted)
    
        DECLARE @queryForInserted NVARCHAR(255)
        DECLARE @queryForDeleted NVARCHAR(255)
    
        DECLARE @Name varchar(MAX)
        DECLARE my_Cursor CURSOR FOR 
        (
            SELECT C.name FROM sys.objects T
            INNER JOIN sys.columns C ON
            T.object_id = C.object_id
            WHERE T.name = 'Projects'
        )
    
        --Creating Temp table for storing single value for each of the column during iteration.
        IF OBJECT_ID('tempdb..#tmpInsertedSingleValue') IS NULL CREATE TABLE #tmpInsertedSingleValue(InsertedValue NVARCHAR(MAX))
    
        IF OBJECT_ID('tempdb..#tmpDeletedSingleValue') IS NULL CREATE TABLE #tmpDeletedSingleValue(DeletedValue NVARCHAR(MAX))
    
        --Creating temp tables and populating them with data from 'inserted' and 'deleted'
        SELECT TOP 1 * INTO #tmpInserted FROM inserted
    
        SELECT TOP 1 * INTO #tmpDeleted FROM deleted
    
        OPEN my_Cursor; 
    
        FETCH NEXT FROM my_Cursor into @Name;
    
            WHILE @@FETCH_STATUS = 0 
            BEGIN
    
                PRINT @Name
    
                -- Creating dynamic sql to select single column value from temp table.
                SET @queryForDeleted = 'SELECT ' + @Name + ' FROM #tmpDeleted'
                SET @queryForInserted = 'SELECT ' + @Name + ' FROM #tmpInserted'
    
                -- Executing dynamic sql to populabe single column value to other temp table.
                INSERT INTO #tmpDeletedSingleValue EXECUTE (@queryForDeleted)
                INSERT INTO #tmpInsertedSingleValue EXECUTE (@queryForInserted)
    
                -- Selecting single value in to variables.
                DECLARE @OldValue NVARCHAR(MAX) = (SELECT TOP 1 * FROM #tmpDeletedSingleValue)
                DECLARE @NewValue NVARCHAR(MAX) = (SELECT TOP 1 * FROM #tmpInsertedSingleValue)
                PRINT  @OldValue
                PRINT  @NewValue
    
                IF (@OldValue <> @NewValue)
                BEGIN
                    INSERT INTO EntityHistory 
                VALUES (1, @Name, @OldValue, @NewValue, @ModifiedBy, GETDATE())
                END
    
                --Clearing SingleValue temp tables after every iteration
                DELETE FROM #tmpDeletedSingleValue
                DELETE FROM #tmpInsertedSingleValue
    
            FETCH NEXT FROM my_Cursor into @Name;
            END
    
        CLOSE my_Cursor; DEALLOCATE my_Cursor;
        -- Clearing temp tables after looping thru all the columns
        DELETE FROM #tmpDeleted
        DELETE FROM #tmpInserted
    END
    

    This should resolve your issue.