0

我有一个 select 语句,我想将它转换为 table 中所有具有 name 的列的更新语句Variable[N]

例如,我想做这些事情:

  1. 我希望能够将下面的 SQL 转换为更新语句。
  2. 我有n名为 的列variable[N]。下面的示例仅更新 column variable63,但我想在不知道我提前有多少列的情况下动态地对所有具有名称variable1的列运行更新。此外,在下面的示例中,我将更新的结果放入. 如果可能的话,我实际上想用结果更新相应的变量列,在下面的示例中。variableNvariable[N]NewColvariable63

我想要一个包装器循环遍历列variable1variableN在所有这些列上执行相同的相应更新操作:

SELECT  
     projectid
    ,documentid
    ,revisionno
    ,configurationid
    ,variable63
    ,ISNULL(Variable63, 
            (SELECT TOP 1 
             variable63 
             FROM table1 
             WHERE 
                 documentid = t.documentid 
             and projectid=t.projectid
             and configurationid=t.configurationid 
             and cast(revisionno as int) < cast(t.revisionno as int) 
             AND Variable63 is NOT NULL 
             ORDER BY 
              projectid desc
             ,documentid desc
             ,revisionno desc
             ,configurationid desc
             )) as NewCol
FROM    table1 t;
4

2 回答 2

0

好的,我想我明白了。循环遍历列并为每列运行更新命令的函数。

DECLARE @sql NVARCHAR(1000),
@cn NVARCHAR(1000)--,
--@r NVARCHAR(1000),
--@start INT

DECLARE col_names CURSOR FOR
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'PIVOT_TABLE'
ORDER BY ordinal_position

--SET @start = 0
DECLARE @op VARCHAR(max)
SET @op=''

OPEN col_names FETCH next FROM col_names INTO @cn

WHILE @@FETCH_STATUS = 0
BEGIN
    --print @cn
    IF UPPER(@cn)<> 'DOCUMENTID' and UPPER(@cn)<> 'CONFIGURATIONID' and UPPER(@cn)<> 'PROJECTID' and UPPER(@cn)<> 'REVISIONNO'
    BEGIN
        SET @sql = 'UPdate pt
        set pt.' + @cn + ' = ((SELECT TOP 1 t.' + @cn + ' FROM pivot_table t WHERE t.documentid = pt.documentid and t.projectid=pt.projectid
        and t.configurationid=pt.configurationid and cast(t.revisionno as int) < cast(pt.revisionno as int) AND t.' + @cn + ' is NOT NULL 
        ORDER BY revisionno desc)) from PIVOT_TABLE pt where pt.' + @cn + ' is NULL;'
        EXEC Sp_executesql
        @sql
        --print @cn
    END
    FETCH next FROM col_names INTO @cn
END

CLOSE col_names
DEALLOCATE col_names;
于 2012-08-13T21:13:49.357 回答
0

没有通用的方法来遍历 SQL 中的变量,您应该确切地知道要修改什么。在某些数据库中,可以查询系统表以动态构建更新语句(我知道如何在 InterBase 和它的前身 Firebird 中做到这一点),但是您没有告诉我们您正在使用哪个数据库引擎。

下面是一种可以更新几个为空的字段的方法,COALESCE 和 CASE 是做同样事情的两种方法,就像使用 LEFT JOIN 或 NOT EXISTS 一样。使用您和您的数据库引擎最熟悉的那些。请注意,所有记录都将被更新,因此如果您的数据库包含数百万条记录,每条记录很大并且您希望此查询被执行很多次,这不是一个好的解决方案。

UPDATE table1 t
SET t.VARIABLE63 = 
  COALESCE(t.VARIABLE63, 
           (SELECT VARIABLE63
            FROM table1 t0
            LEFT JOIN table1 tNot 
                   ON tNot.documentid = t.documentid
                  AND tNot.projectid=t.projectid        
                  AND tNot.configurationid=t.configurationid
                  AND cast(tNot.revisionno as int) > cast(t0.revisionno as int)
                  AND cast(tNot.revisionno as int) < cast(t.revisionno as int)
                  AND tNot.Variable63 is NOT NULL
            WHERE t0.documentid = t.documentid
              AND t0.projectid=t.projectid        
              AND t0.configurationid=t.configurationid
              AND cast(t0.revisionno as int) < cast(t.revisionno as int)
              AND t0.Variable63 is NOT NULL
              AND tNot.Variable63 is NULL)),
    t.VARIABLE64 = CASE WHEN t.VARIABLE64 IS NOT NULL then t.VARIABLE64
                        ELSE (SELECT VARIABLE64
                              FROM table1 t0
                              WHERE t0.documentid = t.documentid
                                AND t0.projectid=t.projectid        
                                AND t0.configurationid=t.configurationid
                                AND cast(t0.revisionno as int) < cast(t.revisionno as int)
                                AND t0.Variable64 is NOT NULL
                                AND NOT EXISTS(SELECT 1 
                                               FROM table1 tNot 
                                               WHERE tNot.documentid = t.documentid
                                                 AND tNot.projectid=t.projectid        
                                                 AND tNot.configurationid=t.configurationid
                                                 AND cast(tNot.revisionno as int) > cast(t0.revisionno as int)
                                                 AND cast(tNot.revisionno as int) < cast(t.revisionno as int)
                                                 AND tNot.Variable64 is NOT NULL)) END
于 2012-07-26T20:59:11.140 回答