You can use a recursive sub-query factoring clause to split the data for any amount:
WITH data ( "ORDER", article, size_1, size_2, size_3 ) AS (
SELECT * FROM qty_split
UNION ALL
SELECT "ORDER",
article,
GREATEST( size_1 - 99, 0 ),
GREATEST( size_2 - 99, 0 ),
GREATEST( size_3 - 99, 0 )
FROM data
WHERE size_1 > 99
OR size_2 > 99
OR size_3 > 99
)
SELECT "ORDER",
article,
LEAST( size_1, 99 ) AS size_1,
LEAST( size_2, 99 ) AS size_2,
LEAST( size_3, 99 ) AS size_3
FROM data
ORDER BY
"ORDER",
article,
ROWNUM;
Which, for the sample data:
create table qty_split (
"ORDER" varchar2(4),
article_code varchar2(4),
size_1 number(3,0),
size_2 number(3,0),
size_3 number(3,0)
);
insert into qty_split
SELECT 'a001', '1111', 123, 165, 85 FROM DUAL UNION ALL
SELECT 'b002', '2222', 312, 45, 17 FROM DUAL UNION ALL
SELECT 'c003', '3333', 0, 0, 417 FROM DUAL;
Outputs:
ORDER | ARTICLE | SIZE_1 | SIZE_2 | SIZE_3
:---- | :------ | -----: | -----: | -----:
a001 | 1111 | 99 | 99 | 85
a001 | 1111 | 24 | 66 | 0
b002 | 2222 | 99 | 45 | 17
b002 | 2222 | 99 | 0 | 0
b002 | 2222 | 99 | 0 | 0
b002 | 2222 | 15 | 0 | 0
c003 | 3333 | 0 | 0 | 99
c003 | 3333 | 0 | 0 | 99
c003 | 3333 | 0 | 0 | 99
c003 | 3333 | 0 | 0 | 99
c003 | 3333 | 0 | 0 | 21
db<>fiddle here