WITH
FUNCTION nl ( s IN varchar2 )
RETURN varchar2
IS
BEGIN
        RETURN chr(10) || s;
END nl;
FUNCTION v ( d NUMBER, x NUMBER, g IN varchar2 )
RETURN varchar2
IS
BEGIN
        RETURN
        CASE WHEN d >= x THEN nl (g) END;
END v;
SELECT 'On the '
        || to_char(to_date(level,'j'),'jspth' )
        || ' day of Christmas,'
        || nl( 'my true love sent to me:')
        || v ( level, 12, 'Twelve drummers drumming,' )
        || v ( level, 11, 'Eleven pipers piping,' )
        || v ( level, 10, 'Ten lords a-leaping,' )
        || v ( level, 9, 'Nine ladies dancing,' )
        || v ( level, 8, 'Eight maids a-milking,' )
        || v ( level, 7, 'Seven swans a-swimming,' )
        || v ( level, 6, 'Six geese a-laying,' )
        || v ( level, 5, 'Five golden rings!' )
        || v ( level, 4, 'Four calling birds,' )
        || v ( level, 3, 'Three French hens,' )
        || v ( level, 2, 'Two turtle doves,' )
        || v ( level, 1, CASE level WHEN 1 THEN 'A' ELSE 'And a' END || ' partridge in a pear tree.' )
        || nl(NULL)
        
FROM dual
CONNECT BY level <= 12
/