2012-07-26 39 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;