我试图在 MySQL 服务器上动态生成的交叉表视图中对一些数据进行非规范化。由于这里有一个有用的答案,我已经成功创建了一个存储过程来生成这个交叉表视图。
这是我的程序:
DELIMITER $$
CREATE PROCEDURE `PartFlow`.`DimMatTab` ()
BEGIN
SET @cols = (
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'\nSUM(IF(dimension_id = ',
dimension_id,
', value, NULL)) AS ',
name
)
) as column_list
FROM PartFlow.tDimMatMap
JOIN PartFlow.tDimension
on tDimension.id_dimension = tDimMatMap.dimension_id
);
SET @sql = CONCAT(
'CREATE OR REPLACE VIEW `PartFlow`.`vDimMatTab` AS '
'SELECT material_id, ',
@cols,
' FROM tDimMatMap ',
'GROUP BY material_id;');
PREPARE stmt FROM @sql;
EXECUTE stmt;
END
这会产生一个包含此查询的视图:
select
`material_id`
,sum(if((`dimension_id` = 2),`value`,NULL)) AS `Width`
,sum(if((`dimension_id` = 3),`value`,NULL)) AS `Height`
,sum(if((`dimension_id` = 5),`value`,NULL)) AS `Thickness`
from `PartFlow`.`tDimMatMap`
group by `material_id`
我希望在对 tDimMatMap 的任何更改上更新视图,以便该视图将始终包含正确的交叉表列。我尝试在此源表上的任何插入、更新或删除上触发该过程。这是我的触发代码:
create trigger update_view_iMat after insert on tDimMatMap
for each row call DimMatTab();$$
create trigger update_view_uMat after update on tDimMatMap
for each row call DimMatTab();$$
create trigger update_view_dMat after delete on tDimMatMap
for each row call DimMatTab();$$
在我看来,这是一个完美的设置,但是当我尝试编辑 tDimMatMap 表时,我收到错误消息“存储函数或触发器中不允许使用动态 SQL”。有没有办法解决这个问题?我是否从错误的角度解决问题?我只是想确保我的交叉表视图始终包含 tDimMatMap 表中列出的每个唯一“dimension_id”的列。
我正在从多个客户端前端访问这些数据,所以这个集中式解决方案似乎是正确的。我相信有些人会说我应该在服务器之外生成我的 SQL 代码,或者运行该过程来获取我的数据而不创建视图,但是我不能在我的客户端中动态更新这个视图,我也不能通过调用我的客户中的程序。最重要的是,该视图将与某些应用程序中的其他视图和表连接,因此创建视图非常重要。