背景 - 我有一个从一个大的平面文件创建的数据库。而不是创建一个包含106列的单个大表。我创建了一个“columns”表,它存储列名和保存该数据的表的id,以及106个其他表来存储每列的数据。由于并非所有记录都包含所有列中的数据,我认为这可能是一种更有效的加载数据的方法(可能是一个坏主意)。
这方面的困难是从这个结构重建单个记录。为此,我创建了以下过程:
DROP PROCEDURE IF EXISTS `col_val`;
delimiter $$
CREATE PROCEDURE `col_val`(IN id INT)
BEGIN
DROP TEMPORARY TABLE IF EXISTS tmp_record;
CREATE TEMPORARY TABLE tmp_record (id INT(11), val varchar(100)) ENGINE=MEMORY;
SET @ctr = 1;
SET @valsql = '';
WHILE (@ctr < 107) DO
SET @valsql = CONCAT('INSERT INTO tmp_record SELECT ',@ctr,', value FROM col',@ctr,' WHERE recordID = ',@id,';');
PREPARE s1 FROM @valsql;
EXECUTE s1;
DEALLOCATE PREPARE s1;
SET @ctr = @ctr+1;
END WHILE;
END$$
DELIMITER ;
然后我使用以下SQL,其中存储过程参数是我想要的记录的id。
CALL col_val(10);
SELECT c.`name`, t.`val`
FROM `columns` c INNER JOIN tmp_record t ON c.ID = t.id
问题 - 我第一次运行它时效果很好。但是,即使参数已更改,每个后续运行也会返回完全相同的记录。即使存储过程应该丢弃并重新创建临时表,这仍然如何?
我可能会重新思考整个设计并回到单个表格,但这个问题说明了我想要了解的内容。
不确定是否重要但我在Windows 7上运行MySQL 5.6(64位)并通过MySQL Workbench v5.2.47 CE执行SQL。
谢谢,
答案 0 :(得分:0)
在MySQL存储过程中,不要在局部变量(输入参数或本地声明的变量)前放置@
符号。您使用的@id
引用了user variable,它有点像您正在调用过程的会话的全局变量。
换句话说,@id
是与id
不同的变量。
这就是你所遇到的直接问题的解释。但是,我不会像你那样设计表格。
由于并非所有记录都包含所有列中的数据,我认为这可能是一种更有效的加载数据的方法
我建议使用传统的单表,并使用NULL表示缺少的数据。