2012-07-26 66 views
0

我有一个选择语句,我想要转换为名称为Variable[N]的表中所有列的更新语句。循环更新多列?

例如,我想要做的这些事情:

  1. 我希望能够到SQL转换成如下的更新语句。
  2. 我有n列名为variable[N]。下面的示例只更新列variable63,但我想要动态运行名称为variable1variableN的所有列上的更新,而不必知道我有多少个variable[N]列。另外,在下面的例子中,我得到更新结果到NewCol。如果可能,我实际上想要更新相应的变量列,variable63在我的示例中。

我想有通过variableN遍历variable1列的包装,并在所有这些列执行相同的各个更新操作:

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; 
+0

您将需要使用动态SQL。我希望你不要期望它快。 – Hogan 2012-07-26 20:12:15

+0

至少告诉我们变量1和变量2的更新语句是什么样子......很难确切知道你要在这里做什么。 – Hogan 2012-07-26 20:13:21

+0

你使用什么数据库? – 2012-07-26 20:25:37

回答

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 
+0

DB是sql server 2008。 – user1491749 2012-07-26 22:18:30

0

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

DECLARE @sql NVARCHAR(1000), 
@cn NVARCHAR(1000)--, 
[email protected] NVARCHAR(1000), 
[email protected] 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;