【问题标题】:Update table from another table using dynamic column references in MySql 5.7使用 MySql 5.7 中的动态列引用从另一个表更新表
【发布时间】:2019-10-23 23:42:37
【问题描述】:

我有两张表 NEW_TBL 和 CURRENT_TBL。

CURRENT_TBL 中的值需要更新,使其等于 NEW_TBL。两个表都有一个名为 tableId 的 PK,但 NEW_TBL 中的列并不总是匹配 CURRENT_TBL。我已经有了使架构相同所需的东西,但我需要一种基于动态列引用更新 CURRENT_TBL 值的方法。

这是我如何在 javascript 中完成此操作的人为示例。

起始表:

currentTable = [
  ['tableId','col2','col3','col4'],
  ['1','purple','blue','pink'],
  ['2','purple','red','orange'],
  ['3','green','yellow','purple']
];


newTable = [
  ['tableId','col2','col3','col4'],
  ['1','','blue','pink'],
  ['2','magenta','blue','pink'],
  ['4','grey','black','white']
];

功能:

function updateCurrentTable() {
  var currentHeader = currentTable[0];
  var newHeader = newTable[0];
  var currentValues = currentTable.slice(1);
  var newValues = newTable.slice(1);

  var newIdList = newValues.map(function(val){ // Get list of newTable ids
    return val[0];
  })

  var currentIdList = currentValues.map(function(val){ // Get list of newTable ids
    return val[0];
  })

  for (var newColumn = 0; newColumn<newHeader.length; newColumn++) { // Loop through new table columns
    var columnName = newHeader[newColumn];
    var newIdColumn = newHeader.indexOf('tableId');
    var currentColumnIndex = currentHeader.indexOf(columnName);
    var currentIdIndex = currentHeader.indexOf('tableId');

    if (columnName !== 'tableId') { // The tableId column is skipped because the id will never be altered

      for (var newRow = 0; newRow<newValues.length; newRow++) { // Loop through new table rows
        var newId = newValues[newRow][newIdColumn];
        var newValue = newValues[newRow][newColumn];

        if (currentIdList.indexOf(newId) < 0) { // If tableId exists in newTable but not in currentTable, add the row to currentTable
          currentValues.push(newValues[newRow]);
          currentIdList.push(newId); // Update the id list
        }

        for (var curRow =0; curRow < currentValues.length; curRow++) { // Loop through current table rows
          var currentId = currentValues[curRow][currentIdIndex];

          if (currentColumnIndex !== currentIdIndex) { // The tableId column is skipped because the id will never be altered

            if (newIdList.indexOf(currentId) < 0) { // If tableId exists in currentTable but not newTable, remove the row from currentTable
              currentValues.splice(curRow,1);
            } else if (newId === currentId) { // If the tableIds match, update the value in the current column
              currentValues[curRow][currentColumnIndex] = newValue; 
            } 
          }
        }
      }
    }
  }

  Logger.log(currentValues)
}

结果:

currentTable = [
  ['tableId','col2','col3','col4'],
  ['1','','blue','pink'],
  ['2','magenta','blue','pink'],
  ['4','grey','black','white']
];

有没有办法在 SQL 中完成上述操作?

谢谢!

【问题讨论】:

    标签: mysql database stored-procedures sql-update compare


    【解决方案1】:

    我了解到您希望匹配 tableId 列上的表格,并使用来自 new_tbl 的相应值更新 current_tbl 中的 colHeader

    为此,您可以利用 MySQL update ... join ... set 语法:

    update current_tbl c
    inner join new_tbl n on c.tableId   = n.tableId
    set c.colHeader = n.colHeader
    

    【讨论】:

    • 谢谢你,GMB。我已经多次遇到这种解决方案,但它仍然需要我手动更新列标题。如何使列引用动态化?如果两个表中的行和列匹配,我想更新表值。
    • 我相信我的问题可能还不清楚。为了清楚起见,我已经编辑并添加了一个示例。
    【解决方案2】:

    我想出了一个解决方案,它动态创建 SQL 语句比较列的部分(即“currentTable.cost = newTable.cost”),然后使用动态列列表运行 UPDATE JOIN。

    DELIMITER //
     CREATE PROCEDURE matchCurrentToNew()
     COMMENT 'Update currentTable to match newTable'
     BEGIN
    
        DECLARE num_rows INT;
        DECLARE col_name TINYTEXT;
        DECLARE concatStatement TINYTEXT;
        DECLARE concatFields TINYTEXT;
        DECLARE done TINYINT DEFAULT FALSE; 
    
        DECLARE col_names 
          CURSOR FOR
            SELECT column_name
            FROM INFORMATION_SCHEMA.COLUMNS
            WHERE table_name = 'TASKS'
            ORDER BY ordinal_position;
    
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
        SET concatStatement = "";
        OPEN col_names;
    
        SELECT FOUND_ROWS() into num_rows;
    
        the_loop: LOOP
    
            FETCH NEXT FROM col_names    
            INTO col_name; 
    
            IF done THEN
              CLOSE col_names;
              LEAVE the_loop;
            END IF;
    
            IF col_name <> "UniqueId" AND col_name <> "ProjectId" THEN
                SET concatFields = CONCAT_WS("=",
                                         CONCAT_WS(".","currentTable",col_name),
                                         CONCAT_WS(".","newTable",col_name)
                                        );
    
                SET concatStatement = CONCAT(concatStatement,",",concatFields);         
            END IF;
    
        END LOOP the_loop;
    
        #     Remove comma at the beginning of the concatStatement string
    
        SET concatStatement = TRIM(LEADING "," FROM concatStatement);
    
        SET @sqlText = CONCAT(
          'UPDATE currentTable  
          JOIN newTable
          ON currentTable .UniqueId = newTable.UniqueId 
          AND currentTable .ProjectId = newTable.ProjectId
          SET ', concatStatement
        );
    
        PREPARE stmt FROM @sqlText;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    
     END //
     DELIMITER ;
    

    【讨论】:

      猜你喜欢
      • 2021-05-30
      • 2012-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多