以下过程可能会奏效。
它将在 INFORMATION_SCHEMA.COLUMNS 表中查找给定 tableName 的所有列名(不包括“userid” - 如果您使用的名称不同,这可能会发生变化)。
该过程还创建了一个临时表(这也有待改进 - 如果在创建之前存在,则最好执行“删除”)以将总和存储到一个点。
循环中的项目只是使用给定的 tableName 参数和来自游标的 columnName 构建一个 SQL UPDATE 语句并进行数学运算。
要对此进行测试(创建后):
调用 myProcedure('tableName');
DELIMITER //
DROP PROCEDURE IF EXISTS myProcedure //
CREATE PROCEDURE
myProcedure( tableName varchar(32) )
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE columnName varchar(64);
DECLARE cur1 CURSOR FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = tableName and COLUMN_NAME <> 'userid';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
CREATE TEMPORARY TABLE intermediateresults(userid integer, sumOfScores integer);
SET @st1 = CONCAT('INSERT INTO intermediateresults (SELECT DISTINCT userid, 0 FROM ',tableName,' )' );
PREPARE stmt3 FROM @st1;
EXECUTE stmt3;
looping: LOOP
FETCH cur1 into columnName;
IF done THEN
LEAVE looping;
END IF;
SET @st1 = CONCAT('UPDATE intermediateresults set sumOfScores = sumOfScores + COALESCE( (SELECT ', columnName, ' FROM ',tableName, ' t WHERE t.userid=intermediateresults.userid) , 0)' );
PREPARE stmt3 FROM @st1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
END LOOP;
CLOSE cur1;
SELECT * FROM intermediateresults;
DROP table intermediateresults;
END
//
DELIMITER ;
做这种事情时可能会感兴趣:
INFORMATION_SCHEMA 还包含以下数据:
DATA_TYPE:可用于测试特定列是否具有您期望的实际类型 - 可以将 DATA_TYPE='int' 等条件添加到游标定义以确保它实际上是一个 int(假设要求和的列实际上是 INT)
ORDINAL_POSITION:如果您知道列的顺序,则可以使用它应该到达(例如,对于最后四个是内务处理的情况)
TABLE_SCHEMA:上面的过程假定该表仅存在于当前默认模式中。使用它需要在过程中添加一个额外的参数,并在构造的 SQL 语句中稍作更改。