问题描述
我需要通过具有可变列数的存储过程在 MysqL 中创建一个临时表,并将表中的数据插入其中。
这就是它的要点,现在有一点背景知识,我继承了一个系统,其中“联系表单”系统可以根据某些条件具有不同数量的字段......以前的团队能够提出的最好的with 是一个表,每次用户提交表单时,都会为该提交分配一个 ID,它会像这样存储:
ID | 身份证件 | 实例 | 字段 | 价值 |
---|---|---|---|---|
0001 | 100001 | 0000001 | 姓名 | 乔 |
0002 | 100001 | 0000001 | 姓氏 | 史密斯 |
0003 | 100001 | 0000001 | 电话 | 2125551212 |
0004 | 100001 | 0000001 | GDPR | 真实 |
0005 | 100001 | 0000002 | 姓名 | 简 |
0006 | 100001 | 0000002 | 姓氏 | 能源部 |
0007 | 100001 | 0000002 | 电话 | 2125551213 |
0008 | 100001 | 0000002 | GDPR | 假 |
0009 | 100001 | 0000003 | 姓名 | 吉姆 |
0010 | 100001 | 0000003 | 姓氏 | 约翰斯 |
0011 | 100001 | 0000003 | 电话 | 2125551214 |
0012 | 100001 | 0000003 | GDPR | 真实 |
0013 | 100001 | 0000004 | 姓名 | 杰克 |
0014 | 100001 | 0000004 | 姓氏 | 娃娃 |
0015 | 100001 | 0000004 | 电话 | 2125551223 |
0016 | 100001 | 0000005 | GDPR | 真实 |
0016 | 100002 | 0000001 | 姓名 | 乔 |
0017 | 100002 | 0000001 | 姓氏 | 史密斯 |
0018 | 100002 | 0000001 | 电话 | 2125551212 |
0019 | 100002 | 0000001 | 居民 | 真实 |
0020 | 100002 | 0000001 | GDPR | 真实 |
0021 | 100002 | 0000002 | 姓名 | 简 |
0022 | 100002 | 0000002 | 姓氏 | 能源部 |
0023 | 100002 | 0000002 | 电话 | 2125551213 |
0024 | 100002 | 0000001 | 居民 | 真实 |
0025 | 100002 | 0000002 | GDPR | 假 |
0026 | 100002 | 0000003 | 姓名 | 吉姆 |
0027 | 100002 | 0000003 | 姓氏 | 约翰斯 |
0028 | 100002 | 0000003 | 电话 | 2125551214 |
0029 | 100002 | 0000001 | 居民 | 真实 |
0030 | 100002 | 0000003 | GDPR | 真实 |
0031 | 100002 | 0000004 | 姓名 | 杰克 |
0032 | 100002 | 0000004 | 姓氏 | 娃娃 |
0033 | 100002 | 0000004 | 电话 | 2125551223 |
0034 | 100002 | 0000001 | 居民 | 真实 |
0035 | 100002 | 0000005 | GDPR | 真实 |
因此,在此示例中,将有 2 种类型的表单,一种有 4 个字段(姓名、姓氏、电话、gdpr),另一种有 5 个字段(姓名、姓氏、电话、居民、gdpr)。>
因此,当我需要查询填写表单类型 100001 的人员时,我需要查询 IDForm = 100001 的所有记录,然后获取唯一实例,然后遍历每个 IDForm/实例组合以获取列表字段然后再次循环以获取值...
这是一场噩梦。
现在想象一下,大约有 1000 种不同类型的表单,其中一些表单有超过 10K 的提交。
当我必须提取这 10K 份提交报告中的一份时,它需要很长时间。
我正在尝试使用存储过程重写整个过程以加快进程。
我想到的是创建一个存储过程,在其中传递 IDForm,该过程将查询表单的实例,获取所述实例的字段,为每个字段创建一个带有一列的临时表,然后遍历版本的记录集并将信息存储在所述临时表中。 (满嘴)
这是我的尝试,无论如何,第一部分,创建表并创建列...
CREATE DEFINER=`root`@`localhost` PROCEDURE `getEdition`(
IN IDForm VARCHAR(15),IN edition varchar(15)
)
BEGIN
DECLARE n int DEFAULT 0;
DECLARE i int DEFAULT 0;
select count( disTINCT p.field) from wp_fields_form_ddbb as p
where p.IDForm COLLATE utf8mb4_general_ci = IDForm
and p.value COLLATE utf8mb4_general_ci != ''
order by p.ID asc into n;
DROP TEMPORARY TABLE IF EXISTS tmpTableName;
CREATE TEMPORARY TABLE IF NOT EXISTS tmpTableName (
MyID INT );
set i=0;
while i<n DO
SET i = i +1;
SET @edition = select p.field from wp_fields_form_ddbb as p
where p.IDForm COLLATE utf8mb4_general_ci = IDForm
and p.value COLLATE utf8mb4_general_ci != ''
order by p.ID asc LIMIT i,1;
SET @ddl = concat('ALTER TABLE ',tmpTableName,' add COLUMN ',/*,*/
' varchar(1024);');
PREPARE STMT FROM @ddl;
EXECUTE STMT;
END WHILE;
END
我什至不确定这是否可行,但如果可行,我将不胜感激各位大师的帮助。
提前致谢!
-奥拉洛
编辑
我终于让它“工作”了,我的意思是,它做了应该做的事情,但仍然需要 foreeeeeever 来处理数据。
我将把代码留在这里,以防它对处于(希望不是)类似情况的人有所帮助。
我有 3 个存储过程,一个获取 IDForm 调用另一个创建列的存储过程,然后它遍历结果将每个提交插入一行。
干杯!
-奥拉洛
CREATE DEFINER=`root`@`localhost` PROCEDURE `getEdition`(IN `IDForm` VARCHAR(15),IN `edition` VARCHAR(15))
MODIFIES sql DATA
BEGIN
DECLARE bDone INT;
DECLARE var1 VARCHAR(256);
DECLARE var2 VARCHAR(256);
DECLARE curs CURSOR FOR select disTINCT p.field from wp_fields_form_ddbb as p
where p.IDForm COLLATE utf8mb4_general_ci = IDForm
and p.value COLLATE utf8mb4_general_ci != ''
order by p.ID asc;
DECLARE cursEditions CURSOR FOR select disTINCT p.edition from wp_fields_form_ddbb as p
where p.IDForm COLLATE utf8mb4_general_ci = IDForm
order by p.ID asc;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
DROP TEMPORARY TABLE IF EXISTS tmpTableName;
CREATE TEMPORARY TABLE IF NOT EXISTS tmpTableName (
MyID INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
OPEN curs;
/* CREATE THE COLUMNS */
SET bDone = 0;
main_loop: LOOP
FETCH curs INTO var1;
IF bDone THEN
LEAVE main_loop;
END IF;
CALL createColumn('tmpTableName',var1,'varchar(256)');
END LOOP;
CLOSE curs;
/* END CREATE THE COLUMNS */
/* SELECT ALL EDITIONS FROM THIS FORM */
OPEN cursEditions;
SET bDone = 0;
editions_loop: LOOP
FETCH cursEditions INTO var2;
IF bDone THEN
LEAVE editions_loop;
END IF;
CALL insertEdition(IDForm,var2);
END LOOP;
CLOSE cursEditions;
/* RETURN THE TABLE */
SELECT * FROM tmpTableName;
END
CREATE DEFINER=`root`@`localhost` PROCEDURE `createColumn`(IN `mytable` VARCHAR(256),IN `colname` VARCHAR(256),IN `mytype` VARCHAR(256))
NO sql
BEGIN
SET @ddl = concat('alter table ',mytable,' add column (',colname,' ',mytype,')');
PREPARE STMT FROM @ddl;
EXECUTE STMT;
END
delimiter $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `insertEdition`(IN `IDForm` VARCHAR(256),IN `edition` VARCHAR(256))
MODIFIES sql DATA
BEGIN
DECLARE bDone INT;
DECLARE varField VARCHAR(4096);
DECLARE varValue VARCHAR(4096);
DECLARE varFieldsTmp VARCHAR(4096) DEFAULT '';
DECLARE varValuesTmp VARCHAR(4096) DEFAULT '';
DECLARE cnt int DEFAULT 1;
DECLARE strsql varchar(4026) DEFAULT '';
DECLARE curs CURSOR FOR select p.field,p.value from wp_fields_form_ddbb as p
where p.IDForm COLLATE utf8mb4_general_ci = IDForm
and p.edition COLLATE utf8mb4_general_ci = edition
and p.value != ''
order by p.ID asc;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
SET strsql = "INSERT INTO tmpTableName (";
OPEN curs;
/* INSERT THE ROW */
SET bDone = 0;
main_loop: LOOP
FETCH curs INTO varField,varValue;
IF bDone THEN
LEAVE main_loop;
END IF;
if (!INSTR(varFieldsTmp,varField)) THEN
if (cnt = 1) THEN
set varFieldsTmp = CONCAT(varFieldsTmp,varField);
set varValuesTmp = CONCAT(varValuesTmp,'"',varValue,'"');
ELSE
set varFieldsTmp = CONCAT(varFieldsTmp,',"','"');
END IF;
END IF;
SET cnt = cnt + 1;
END LOOP;
CLOSE curs;
SET strsql = CONCAT(strsql,varFieldsTmp,") VALUES (",varValuesTmp,");");
PREPARE stmt FROM strsql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)