【问题标题】:Sql: Query returns column name instead of ValueSql:查询返回列名而不是值
【发布时间】:2017-08-22 11:05:02
【问题描述】:

我有这样的结构,可以在更新后触发器中使用动态列名

这两个查询通过这条语句返回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

【问题讨论】:

  • 您不能传递变量以在选择查询中具有列名。它将作为查询中的静态值注入。喜欢SELECT 'colName' FROM DELETED。这将导致返回相同的值colName,而不是表中该列的实际数据。您可以在 SSMS 中运行这个简单的示例,看看它是如何工作的。
  • 是的,这是我的问题,我怎样才能得到这个查询的结果
  • products 表中有多少列?
  • 我有超过 20 列
  • 所有列都是 NVARCHAR(MAX) ?

标签: sql dynamic cursor


【解决方案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

这应该可以解决您的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    相关资源
    最近更新 更多