Be very afraid:
with ArabicRomanConversions as ( select * from ( values ( 0, '', '', '', '' ), ( 1, 'I', 'X', 'C', 'M' ), ( 2, 'II', 'XX', 'CC', 'MM' ), ( 3, 'III', 'XXX', 'CCC', 'MMM' ), ( 4, 'IV', 'XL', 'CD', '?' ), ( 5, 'V', 'L', 'D', '?' ), ( 6, 'VI', 'LX', 'DC', '?' ), ( 7, 'VII', 'LXX', 'DCC', '?' ), ( 8, 'VIII', 'LXXX', 'DCCC', '?' ), ( 9, 'IX', 'XC', 'CM', '?' ) ) as Placeholder ( Arabic, Ones, Tens, Hundreds, Thousands ) ), OrdinalConversions as ( select * from ( values ( 1, 'st' ), ( 2, 'nd' ), ( 3, 'rd' ), ( 11, 'th' ), ( 12, 'th' ), ( 13, 'th' ) ) as Placeholder2 ( Number, Suffix ) ), Numbers as ( select 1 as Number union all select Number + 1 from Numbers where Number < 3999 ) select Number as Arabic, ( select Thousands from ArabicRomanConversions where Arabic = Number / 1000 ) + ( select Hundreds from ArabicRomanConversions where Arabic = Number / 100 % 10 ) + ( select Tens from ArabicRomanConversions where Arabic = Number / 10 % 10 ) + ( select Ones from ArabicRomanConversions where Arabic = Number % 10 ) as Roman, Cast( Number as VarChar(4) ) + Coalesce( ( select top 1 Suffix from OrdinalConversions where Number = Numbers.Number % 100 or Number = Numbers.Number % 10 order by Number desc ), 'th' ) as Ordinal from Numbers option ( MaxRecursion 3998 );