你好,我有一个有很多属性的表配置文件,配置文件有父级但父级可以有父级等等。 我想获取所有属性列表(甚至是父母的属性) 我用 mysql 5.1.42 编写了这个存储过程,但它只返回配置文件的属性,不包括父母的属性 ...
CREATE DEFINER=`root`@`localhost` PROCEDURE `get_all_attributes`(IN profile_id INT)
BEGIN
DECLARE parent_id INT DEFAULT NULL;
-- Get the attributes for the current profile
SELECT
Id, attribut_rank, attribut_type, create_date, editor, label, memo, name, profile
FROM
marketing_profile_attribut
WHERE
profile = profile_id
ORDER BY
attribut_rank;
-- Get the parent ID for the current profile
SELECT
parent
INTO
parent_id
FROM
marketing_profile
WHERE
Id = profile_id;
-- If the parent ID is not null, call the stored procedure recursively with the parent ID
IF parent_id IS NOT NULL THEN
CALL get_all_attributes(parent_id);
END IF;
END
...
你能告诉我这个程序有什么问题我正在使用 mysql 5.1.42
按原样尝试这个(它适用于我的数据库):
CREATE PROCEDURE `get_all_attributes2`(IN p_profile INT)
BEGIN
DECLARE not_found INT DEFAULT FALSE;
DECLARE parent_id INT DEFAULT NULL;
DECLARE cur_data CURSOR FOR
SELECT parent
FROM marketing_profile
WHERE Id = p_profile;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET not_found = TRUE;
SET @@max_sp_recursion_depth = 100;
CREATE TEMPORARY TABLE IF NOT EXISTS temp_attributes (
Id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(45) DEFAULT NULL,
memo VARCHAR(1000) DEFAULT NULL,
label VARCHAR(45) DEFAULT NULL,
editor INT(10) UNSIGNED DEFAULT NULL,
attribut_type INT(10) UNSIGNED DEFAULT NULL,
profile INT(10) UNSIGNED DEFAULT NULL,
create_date DATETIME DEFAULT NULL,
attribut_rank INT(10) UNSIGNED DEFAULT NULL,
PRIMARY KEY (Id)
);
-- insert the attributes of p_profile into temporary table
INSERT INTO temp_attributes
SELECT Id, name, memo, label, editor, attribut_type, profile, create_date, attribut_rank
FROM marketing_profile_attribut
WHERE profile = p_profile;
OPEN cur_data;
data_loop: LOOP
FETCH cur_data
INTO parent_id;
IF not_found THEN
LEAVE data_loop;
END IF;
CALL get_all_attributes2(parent_id);
END LOOP;
CLOSE cur_data;
select * from temp_attributes
order by attribut_rank;
DROP TABLE temp_attributes;
END
检查MySQL的
max_sp_recursion_depth
设置。由于您只是从树中寻找直接父级,因此您可以使用游标循环而不是递归。
最好的解决方案是将旧的 MySQL 版本更新到更新的版本,您可以为此使用通用表表达式。
有几件事使程序无法正常工作。
考虑到以上两点,程序可能是这样的:
CREATE PROCEDURE `get_all_attributes`(IN profile_id INT)
BEGIN
DECLARE parent_id INT DEFAULT NULL;
CREATE TEMPORARY TABLE IF NOT EXISTS temp_table
AS SELECT
Id, attribut_rank, attribut_type, create_date, editor, label, memo, name, profile
FROM
marketing_profile_attribut;
SET @@max_sp_recursion_depth = 100;
-- Get the attributes for the current profile
INSERT INTO temp_table(Id, create_date)
SELECT
Id, attribut_rank, attribut_type, create_date, editor, label, memo, name, profile
FROM
marketing_profile_attribut
WHERE
profile = profile_id
ORDER BY
Id;
-- Get the parent ID for the current profile
SELECT
parent
INTO
parent_id
FROM
marketing_profile
WHERE
Id = profile_id;
-- If the parent ID is not null, call the stored procedure recursively with the parent ID
IF parent_id IS NOT NULL THEN
CALL get_all_attributes(parent_id);
else
select * from temp_table;
DROP TABLE temp_table;
end if;
END
谢谢你的回答 我尝试使用临时表作为建议的解决方案,但在使用 repeat until 时结果相同,使用以下函数 创建定义器=
root
@localhost
过程get_all_attributes
(在p_profile INT中)
开始
声明完成 INT DEFAULT FALSE;
声明父 INT;
DECLARE cur CURSOR FOR SELECT parent FROM marketing_profile WHERE Id = p_profile;
为 NOT FOUND SET 声明继续处理程序 done = TRUE;
CREATE TEMPORARY TABLE temp_attributes (
Id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(45) DEFAULT NULL,
memo VARCHAR(1000) DEFAULT NULL,
label VARCHAR(45) DEFAULT NULL,
editor INT(10) UNSIGNED DEFAULT NULL,
attribut_type INT(10) UNSIGNED DEFAULT NULL,
profile INT(10) UNSIGNED DEFAULT NULL,
create_date DATETIME DEFAULT NULL,
attribut_rank INT(10) UNSIGNED DEFAULT NULL,
PRIMARY KEY (Id)
);
INSERT INTO temp_attributes
SELECT Id, name, memo, label, editor, attribut_type, profile, create_date, attribut_rank
FROM marketing_profile_attribut
WHERE profile = p_profile
ORDER BY attribut_rank;
SET parent = p_profile;
WHILE NOT done DO
SELECT parent INTO parent FROM marketing_profile WHERE Id = parent;
IF parent IS NOT NULL THEN
INSERT INTO temp_attributes
SELECT Id, name, memo, label, editor, attribut_type, profile, create_date, attribut_rank
FROM marketing_profile_attribut
WHERE profile = parent
ORDER BY attribut_rank;
END IF;
END WHILE;
SELECT * FROM temp_attributes;
DROP TEMPORARY TABLE IF EXISTS temp_attributes;
结束
您的存储过程的问题是您只选择当前配置文件的属性,而不是递归地选择所有父配置文件的属性。您需要修改存储过程以递归地选择所有父配置文件的属性。
您可以通过使用递归公用表表达式 (CTE) 来选择所有父配置文件的属性来实现此目的。不幸的是,MySQL 5.1 不支持 CTE,但您可以使用临时表来实现相同的结果。
这里是一个示例存储过程,它使用临时表递归地选择所有父配置文件的属性:
CREATE DEFINER=`root`@`localhost` PROCEDURE `get_all_attributes`(IN profile_id INT)
BEGIN
-- Create a temporary table to store the attributes for all parent profiles
CREATE TEMPORARY TABLE temp_attributes (
Id INT,
attribut_rank INT,
attribut_type VARCHAR(255),
create_date DATETIME,
editor VARCHAR(255),
label VARCHAR(255),
memo TEXT,
name VARCHAR(255),
profile INT
);
DECLARE parent_id INT DEFAULT NULL;
-- Get the attributes for the current profile and insert them into the temporary table
INSERT INTO temp_attributes
SELECT
Id, attribut_rank, attribut_type, create_date, editor, label, memo, name, profile
FROM
marketing_profile_attribut
WHERE
profile = profile_id;
-- Get the parent ID for the current profile
SELECT
parent
INTO
parent_id
FROM
marketing_profile
WHERE
Id = profile_id;
-- If the parent ID is not null, recursively insert the attributes for all parent profiles into the temporary table
IF parent_id IS NOT NULL THEN
CALL get_all_attributes(parent_id);
INSERT INTO temp_attributes
SELECT
Id, attribut_rank, attribut_type, create_date, editor, label, memo, name, profile
FROM
temp_attributes
WHERE
profile = parent_id;
END IF;
-- Select all the attributes from the temporary table
SELECT * FROM temp_attributes;
-- Drop the temporary table
DROP TEMPORARY TABLE IF EXISTS temp_attributes;
END
在此存储过程中,创建了一个名为 temp_attributes 的临时表来存储所有父配置文件的属性。 INSERT INTO 语句用于将当前配置文件的属性插入到临时表中。如果父 ID 不为空,则使用父 ID 递归调用存储过程,并将所有父配置文件的属性插入到临时表中。最后,从临时表中选择所有属性,并删除临时表。
注意DROP TEMPORARY TABLE IF EXISTS语句用于确保临时表总是在存储过程结束时被删除,即使发生错误。
其实也有例外 为此我做了一些更正..结果函数 创建定义器=
root
@localhost
过程get_all_attributes
(IN profile_id INT)
开始
DECLARE parent_id INT DEFAULT NULL;
CREATE TEMPORARY TABLE IF NOT EXISTS temp_table
AS SELECT
Id, attribut_rank, attribut_type, create_date, editor, label, memo, name, profile
FROM
marketing_profile_attribut
where profile= profile_id
group by Id
;
SET @@max_sp_recursion_depth = 100;
-- 获取当前配置文件的属性 INSERT INTO temp_table (Id, attribut_rank, attribut_type, create_date, editor,
label
, memo, name, profile)
选择 Id, attribut_rank, attribut_type, create_date, editor, label, memo, name, profile 从 营销资料属性 在哪里 配置文件 = profile_id 订购方式 编号;
-- 获取当前配置文件的父 ID 选择 父母 进入 parent_id 从 营销资料 在哪里 id = profile_id;
-- 如果parent ID不为null,则用parent ID递归调用存储过程 如果 parent_id 不为 NULL 那么 CALL get_all_attributes(parent_id); 否则
select * from temp_table group by Id order by (attribut_rank);
end if;
结束