英文:
Stored procedure isn't returning the related table data
问题
希望有人能帮我编写一个存储过程,该过程循环遍历所有租户并获取属性以及相关图像。属性和图像表通过imageables表具有多态关系。以下是简化的表格:
properties
----------
id
title
location
images
--------
id
url
imageables
----------
image_id -- 引用images表
imageable_id -- 引用properties表中的id
imageable_type -- 例如 App\Property 或 App\Room
以下是存储过程:
CREATE PROCEDURE `getAllPropertiesWithImages`()
DETERMINISTIC
COMMENT 'test'
BEGIN
DECLARE queryString TEXT DEFAULT '';
DECLARE tenant_db_id VARCHAR(255) DEFAULT '';
DECLARE done INTEGER DEFAULT 0;
-- 游标以获取不同的租户数据库ID
DECLARE tenant_cursor CURSOR FOR
SELECT DISTINCT(table_schema)
FROM information_schema.TABLES
WHERE table_schema LIKE 'tenant%';
-- 游标未找到的继续处理程序
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET done = 1;
OPEN tenant_cursor;
read_loop: LOOP
FETCH tenant_cursor INTO tenant_db_id;
IF done = 1 THEN
LEAVE read_loop;
END IF;
IF queryString != '' THEN
SET queryString = CONCAT(queryString, ' UNION ALL ');
END IF;
-- 为每个租户的属性附加SELECT查询,其中包括图像URL的JSON
SET queryString = CONCAT(
queryString,
' SELECT
p.id,
p.title,
p.published as is_live,
JSON_ARRAYAGG(i.url) AS images
FROM `', tenant_db_id, '`.properties AS p
LEFT JOIN `', tenant_db_id, '`.imageables AS ia ON p.id = ia.imageable_id AND ia.imageable_type="App\\Property"
LEFT JOIN `', tenant_db_id, '`.images AS i ON ia.image_id = i.id AND i.deleted_at IS NULL
WHERE p.deleted_at IS NULL
GROUP BY p.id'
);
END LOOP;
CLOSE tenant_cursor;
SET @qStr = CONCAT('CREATE OR REPLACE VIEW allPropertiesWithImagesView AS ', queryString);
PREPARE stmt FROM @qStr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @qStr = NULL;
END
问题在于当我运行该过程时,属性的图像列会显示[null]
。然而,在租户数据库上运行查询会给出正确的结果。有人能帮助识别问题,找出我做错了什么吗?
英文:
I hope some one can help me with a stored procedure which loops through all tenants and get properties along with images. The property and images table have a polymorphic relationship through imageables table. Here are the simplified tables;
properties
----------
id
title
location
images
--------
id
url
imageables
----------
image_id -- references images table
imageable_id -- references id on properties table
imageable_type -- e.g. App\Property or App\Room
Following is the stored procedure
CREATE PROCEDURE `getAllPropertiesWithImages`()
DETERMINISTIC
COMMENT 'test'
BEGIN
DECLARE queryString TEXT DEFAULT '';
DECLARE tenant_db_id VARCHAR(255) DEFAULT '';
DECLARE done INTEGER DEFAULT 0;
-- Cursor to fetch distinct tenant database IDs
DECLARE tenant_cursor CURSOR FOR
SELECT DISTINCT(table_schema)
FROM information_schema.TABLES
WHERE table_schema LIKE 'tenant%';
-- Continue handler for cursor not found
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET done = 1;
OPEN tenant_cursor;
read_loop: LOOP
FETCH tenant_cursor INTO tenant_db_id;
IF done = 1 THEN
LEAVE read_loop;
END IF;
IF queryString != '' THEN
SET queryString = CONCAT(queryString, ' UNION ALL ');
END IF;
-- Append the SELECT query for each tenant's properties with image URLs as JSON
SET queryString = CONCAT(
queryString,
' SELECT
p.id,
p.title,
p.published as is_live,
JSON_ARRAYAGG(i.url) AS images
FROM `', tenant_db_id, '`.properties AS p
LEFT JOIN `', tenant_db_id, '`.imageables AS ia ON p.id = ia.imageable_id AND ia.imageable_type="App\\Property"
LEFT JOIN `', tenant_db_id, '`.images AS i ON ia.image_id = i.id AND i.deleted_at IS NULL
WHERE p.deleted_at IS NULL
GROUP BY p.id'
);
END LOOP;
CLOSE tenant_cursor;
SET @qStr = CONCAT('CREATE OR REPLACE VIEW allPropertiesWithImagesView AS ', queryString);
PREPARE stmt FROM @qStr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @qStr = NULL;
END
The problem is that when i run the procedure, it gives me [null]
in images column for the properties. However, running the query on the tenant database gives me correct results. Can some one help to identify the issue as what am i doing wrong?
答案1
得分: 0
留下答案供将来遇到相同问题的任何人使用。由于我正在检查 imageable_type
是否为 App\Property
,我需要按照以下方式进行操作:
imageable_type="App\\\\Property"
这是为什么的解释,
> 在 MySQL 中,反斜杠是转义字符,当您想要在字符串中包含一个字面上的反斜杠时,您需要使用双反斜杠 (\) 进行转义。
由于 imageable_type
是一个字符串值,我希望它被存储为 App\Property,所以我需要在查询中使用 App\\\\Property
。
原因如下:
第一个反斜杠 () 用于转义第二个反斜杠,结果在字符串中产生一个单独的反斜杠。
但是,在与 MySQL 一起工作时,反斜杠也是字符串中的转义字符,所以我需要再次使用两个反斜杠 (\) 来转义反斜杠。
因此,为了将值 App\Property 作为字符串存储在 MySQL 中,我需要在查询中使用 App\\Property。
查询中的四个反斜杠 (\\) 将被 MySQL 解释为一个单独的反斜杠 (\),并且存储在数据库中的结果值将为 App\Property。
英文:
Leaving an answer for any body that would come across the same problem in the future. As I am checking imageable_type
to be App\Property
. I needed to do as follow;
imageable_type="App\\\\property"
Here is the explanation as why,
> In MySQL, backslashes are escape characters, and when you want to
> include a literal backslash in a string, you need to escape it by
> using double backslashes (\)
. Since imageable_type is a string value, and I wanted it to be stored as App\Property, I needed to use App\\\\Property
in the query.
Here's why:
The first backslash () is used to escape the second backslash, resulting in a single backslash in the string.
However, when working with MySQL, backslashes are also escape characters in strings, so I needed to escape the backslash again by using two backslashes (\).
Therefore, to store the value App\Property as a string in MySQL, I needed to use App\\Property in the query.
The quadruple backslashes (\\) in the query will be interpreted by MySQL as a single backslash (\), and the resulting value stored in the database will be App\Property
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论