MariaDB为ROW类型的变量动态提取列
据我在mariadb文档中看到的,您不能直接执行。行类型也没有循环支持。但是,我建议只保留信息_SCHEMA.COLUMNS游标并生成动态选择,如 读循环:循环 将c_列提取到col中; 如果这样做的话 离开read_循环; 如果结束; 将@SQL:=CONCAT'SELECT',col'设置为@colval FROM`',在'tbl'名称中,'WHERE row\u id=',在'u row\u id'中; 从@SQL准备stmt; 使用col执行stmt; 解除分配准备stmt; 设置@create_list:=CONCAT@create_list","col","col","col","colval",; 结束循环读取循环; 由于您只拆分一个表行,这就足够了 更新:有额外的信息,它可以这样做。重新思考之后: set@SQL:=“选择CONCAT”; 读循环:循环 将c_列提取到col中; 如果这样做的话 离开read_循环; 如果结束; SET@SQL:=CONCAT@SQL,“\\”,列,“\\”,“\\”,列,“\\”,”; 结束循环读取循环; set@SQL:=substring@SQL,1,CHAR_LENGTH@SQL - 3; set@SQL:=concat@SQL,进入@create_list FROM`',在` tbl_name',` WHERE row_id=',在` row_id'中; 从@SQL准备stmt; 使用col执行stmt; 解除分配准备stmt;MariaDB为ROW类型的变量动态提取列,mariadb,mariadb-10.3,Mariadb,Mariadb 10.3,据我在mariadb文档中看到的,您不能直接执行。行类型也没有循环支持。但是,我建议只保留信息_SCHEMA.COLUMNS游标并生成动态选择,如 读循环:循环 将c_列提取到col中; 如果这样做的话 离开read_循环; 如果结束; 将@SQL:=CONCAT'SELECT',col'设置为@colval FROM`',在'tbl'名称中,'WHERE row\u id=',在'u row\u id'中; 从@SQL准备stmt; 使用col执行stmt; 解除分配准备stmt; 设置@cr
@谢谢你的支持。我对你的答案做了一些调整,增加了对空字符和转义字符的支持。以下是最后的程序
delimiter $$
CREATE OR REPLACE PROCEDURE `populate_audit_helper_new3`(
IN in_db_name VARCHAR(100),
IN in_tbl_name VARCHAR(100),
IN in_row_id INT(10)
)
proc: BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE col CHAR(40);
DECLARE val TEXT(10000);
DECLARE q TEXT(100000);
DECLARE c_columns CURSOR FOR
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = in_db_name
AND table_name = in_tbl_name
ORDER BY ordinal_position;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN c_columns;
SET q = "";
SET @val = "";
read_loop: LOOP
FETCH c_columns INTO col;
IF done THEN
LEAVE read_loop;
END IF;
SET q = CONCAT(q, "'", col, "','|', IFNULL(QUOTE(", col, "), ''),'$'");
END LOOP read_loop;
SET q = TRIM(TRAILING "," FROM q);
SET q = CONCAT("CONCAT(", q, ") INTO @val");
EXECUTE IMMEDIATE CONCAT("SELECT ", q , " FROM ", in_tbl_name, " WHERE row_id = ", in_row_id);
IF @val = '' THEN
LEAVE proc;
END IF;
SELECT CONCAT("'", REPLACE(@val, "|", "',"), "'") INTO @val;
SELECT REPLACE(@val, "$", ",") INTO @val;
SELECT TRIM(TRAILING ",'" FROM @val) INTO @val;
EXECUTE IMMEDIATE CONCAT("INSERT INTO x1 SET dynamic_cols_l1 = COLUMN_CREATE(", @val, ")" );
CLOSE c_columns;
END$$
我不明白,你在读循环中做了什么你得到了专栏名和什么?可以在开始时执行stmt。rec是ROW类型的变量,因此它有多个列。所以我想在循环的每次迭代中一个接一个地获取每个列,列的名称也是一个变量'col',它在每次迭代中都会改变,但rec不会。我试过准备好的语句,它不起作用。错误是rec是游标类型,而不是表。您必须做的是首先在所有列中运行,然后在所有行中运行。这更合理,但我仍然没有得到你想要达到的目标。我从未见过带有SELECt*的光标。你应该用具体的数据示例来解释你试图实现的目标。我删除了mysql标记,因为mysql没有行数据类型或语法类型。该过程在MySQL上不起作用。@nbk我已更新了计划生成的最终查询。这里唯一的问题是,它在每次迭代中插入rec.name的值。相反,我想要rec.col的值,其中col是一个变量。col的值之一是name。不能使用?列名的占位符。在准备语句时,所有标识符表、列等都必须固定。但是,您应该在\u row\u id中参数化,而不是将其连接到SQL字符串中。但你不是。不,我不应该。它是存储过程的参数,所以保持它的静态是更好的主意。感谢您关于列名的注释howeverThis将为每一列运行一个查询,我不想这样做,因为我计划在所有表的每次更新上通过触发器调用此过程。这就是您最初在问题中所做的
delimiter $$
CREATE OR REPLACE PROCEDURE `populate_audit_helper_new3`(
IN in_db_name VARCHAR(100),
IN in_tbl_name VARCHAR(100),
IN in_row_id INT(10)
)
proc: BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE col CHAR(40);
DECLARE val TEXT(10000);
DECLARE q TEXT(100000);
DECLARE c_columns CURSOR FOR
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = in_db_name
AND table_name = in_tbl_name
ORDER BY ordinal_position;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN c_columns;
SET q = "";
SET @val = "";
read_loop: LOOP
FETCH c_columns INTO col;
IF done THEN
LEAVE read_loop;
END IF;
SET q = CONCAT(q, "'", col, "','|', IFNULL(QUOTE(", col, "), ''),'$'");
END LOOP read_loop;
SET q = TRIM(TRAILING "," FROM q);
SET q = CONCAT("CONCAT(", q, ") INTO @val");
EXECUTE IMMEDIATE CONCAT("SELECT ", q , " FROM ", in_tbl_name, " WHERE row_id = ", in_row_id);
IF @val = '' THEN
LEAVE proc;
END IF;
SELECT CONCAT("'", REPLACE(@val, "|", "',"), "'") INTO @val;
SELECT REPLACE(@val, "$", ",") INTO @val;
SELECT TRIM(TRAILING ",'" FROM @val) INTO @val;
EXECUTE IMMEDIATE CONCAT("INSERT INTO x1 SET dynamic_cols_l1 = COLUMN_CREATE(", @val, ")" );
CLOSE c_columns;
END$$
delimiter $$
CREATE OR REPLACE PROCEDURE `populate_audit_helper_new5`(
IN in_db_name VARCHAR(100),
IN in_tbl_name VARCHAR(100),
IN in_row_id INT(10)
)
proc: BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE create_list TEXT(10000);
DECLARE col TEXT(10000);
DECLARE c_columns CURSOR FOR
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = in_db_name
AND table_name = in_tbl_name
ORDER BY ordinal_position;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN c_columns;
set @SQL := 'SELECT CONCAT(\'';
read_loop: LOOP
FETCH c_columns INTO col;
IF done THEN
LEAVE read_loop;
END IF;
SET @SQL := CONCAT(@SQL, "\\'", col, "\\'\', \', \', IFNULL(QUOTE(", col, "), \'\'), '\, ");
END LOOP read_loop;
set @SQL := substring(@SQL, 1, CHAR_LENGTH(@SQL) - 5);
set @SQL := concat(@SQL, ') into @create_list FROM `', in_tbl_name, '` WHERE row_id = ', in_row_id);
PREPARE stmt FROM @SQL;
execute stmt;
DEALLOCATE PREPARE stmt;
EXECUTE IMMEDIATE CONCAT("INSERT INTO x1 SET dynamic_cols_l1 = COLUMN_CREATE(", @create_list, ")" );
CLOSE c_columns;
END$$