问题描述
正常情况下,多列表的值在数据库中是这种形式存储的:“,id1,id2,”。但当多列表的值非常多时,可能会超出varchar2的存储范围。Agile会直接存一个“,-1,”代替。那真正的值存在哪里呢?
场景描述
在变更单第三页中配置一个多列表物件字段,受影响部件。界面如下
目前物件数量有36个,在数据库中发现值已经变成‘,-1,’ 。如果将部件数量减少至10以内。数据库里面的值又会变成“,id1,id2,”的形式。
解决方案
通过研究表结构发现。当多列表值的个数超出一定范围后。Agile会将值分成很多行存在msatt表中。通过parentid来关联数据表的id。用attid字段区分同一条数据的不同字段。
关联查询SQL如下:
-- 变更关联查询多列表
select c.id,c.change_number,c.multilist31,m.value,i.item_number
from change_p2p3 c
left join msatt m on m.parentid = c.id and m.attid = 1564
left join item i on m.value = i.id
where c.change_number = 'RC0000686';
-- 根据值的类型动态判断是否要去关联表查询。
select c.id,c.change_number,
case when (c.multilist31 = ',-1,') then
(
select ',' || LISTAGG(m.VALUE, ',') WITHIN GROUP (ORDER BY m.created) || ','
from msatt m
where m.parentid = c.id and m.attid = 1564
group by m.parentid
)
else
c.multilist31
end as item_list
from change_p2p3 c
where c.change_number in ('RC0000686','RC0000687','RC0000674');
查询结果1:
查询结果2:
然后通过多列表的值再查询关联的物件或其他对象。
补充方案
第2个SQL由于是通过聚合函数将多行合并成1行,如果超过4000还是会报错。所以这里有个补充方案。可以在后台程序中先查询出多列表的原始值。如果得到‘,-1,’在通过msatt表来查询出所有的值。