Sql:Query返回列名而不是Value

时间:2017-03-29 05:54:18

标签: sql dynamic cursor

我有这样的结构在After Update触发器中使用动态列名

这两个查询通过此语句返回ColumnName而不是Value

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

如何从中获取值然后存储到变量中?

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

1 个答案:

答案 0 :(得分:1)

最后,我能够为您的问题找到解决方案。它涉及临时表。不建议过度使用临时表,但我找不到更好的解决方案。

以下是我创建的ALTER TRIGGER脚本,它非常适合我的桌面。

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

这可以解决您的问题。