Piet, 64 Codels 
With codelsize 20:

Npiet trace images
First loop:

Remaining trace for n=2:

Notes
No Piet answer yet? Let me fix that with my first ever Piet program! This could probably be shorter with better rolls and less pointer manipulation though...
The upper supported limit depends on the implementation of the interpreter. It would theoretically be possible to support arbitraryly large numbers with the right interpreter.
The delimeter is ETX (Ascii 3), however this cannot be properly displayed in this answer so I'll just leave them out. It works in the console:

Output
Input: 1 Output: 1 Input: 20 Output: 1234567891011121314151617181920 Input: 100 Output: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 Undefined behaviour: Input: -1 Output: 1 Input: 0 Output: 1
Npiet trace for n=2
trace: step 0 (0,0/r,l nR -> 1,0/r,l lB): action: in(number) ? 2 trace: stack (1 values): 2 trace: step 1 (1,0/r,l lB -> 2,0/r,l nB): action: push, value 1 trace: stack (2 values): 1 2 trace: step 2 (2,0/r,l nB -> 3,0/r,l nG): action: duplicate trace: stack (3 values): 1 1 2 trace: step 3 (3,0/r,l nG -> 4,0/r,l dY): action: out(number) 1 trace: stack (2 values): 1 2 trace: step 4 (4,0/r,l dY -> 5,0/r,l lY): action: push, value 1 trace: stack (3 values): 1 1 2 trace: step 5 (5,0/r,l lY -> 6,0/r,l lG): action: add trace: stack (2 values): 2 2 trace: step 6 (6,0/r,l lG -> 7,0/r,l lR): action: duplicate trace: stack (3 values): 2 2 2 trace: step 7 (7,0/r,l lR -> 10,0/r,l nR): action: push, value 3 trace: stack (4 values): 3 2 2 2 trace: step 8 (10,0/r,l nR -> 12,0/r,l dR): action: push, value 2 trace: stack (5 values): 2 3 2 2 2 trace: step 9 (12,0/r,l dR -> 13,0/r,l lB): action: roll trace: stack (3 values): 2 2 2 trace: step 10 (13,0/r,l lB -> 14,0/r,l lG): action: duplicate trace: stack (4 values): 2 2 2 2 trace: step 11 (14,0/r,l lG -> 15,2/d,r nG): action: push, value 3 trace: stack (5 values): 3 2 2 2 2 trace: step 12 (15,2/d,r nG -> 15,3/d,r dG): action: push, value 1 trace: stack (6 values): 1 3 2 2 2 2 trace: step 13 (15,3/d,r dG -> 14,3/l,l lR): action: roll trace: stack (4 values): 2 2 2 2 trace: step 14 (14,3/l,l lR -> 13,1/l,r lC): action: greater trace: stack (3 values): 0 2 2 trace: step 15 (13,1/l,r lC -> 11,1/l,r nC): action: push, value 3 trace: stack (4 values): 3 0 2 2 trace: step 16 (11,1/l,r nC -> 10,1/l,r lB): action: multiply trace: stack (3 values): 0 2 2 trace: step 17 (10,1/l,r lB -> 9,1/l,r nY): action: pointer trace: stack (2 values): 2 2 trace: step 18 (9,1/l,r nY -> 7,1/l,r dY): action: push, value 2 trace: stack (3 values): 2 2 2 trace: step 19 (7,1/l,r dY -> 6,1/l,r lY): action: push, value 1 trace: stack (4 values): 1 2 2 2 trace: step 20 (6,1/l,r lY -> 5,1/l,r nM): action: roll trace: stack (2 values): 2 2 trace: step 21 (5,1/l,r nM -> 4,1/l,r dM): action: push, value 3 trace: stack (3 values): 3 2 2 trace: step 22 (4,1/l,r dM -> 3,1/l,r lG): action: pointer trace: stack (2 values): 2 2 trace: step 23 (3,1/d,r lG -> 2,3/l,l nG): action: push, value 3 trace: stack (3 values): 3 2 2 trace: step 24 (2,3/l,l nG -> 2,2/u,r lY): action: out(char) trace: stack (2 values): 2 2 trace: white cell(s) crossed - continuing with no command at 2,0... trace: step 25 (2,2/u,r lY -> 2,0/u,r nB): trace: step 26 (2,0/u,r nB -> 3,0/r,l nG): action: duplicate trace: stack (3 values): 2 2 2 trace: step 27 (3,0/r,l nG -> 4,0/r,l dY): action: out(number) 2 trace: stack (2 values): 2 2 trace: step 28 (4,0/r,l dY -> 5,0/r,l lY): action: push, value 1 trace: stack (3 values): 1 2 2 trace: step 29 (5,0/r,l lY -> 6,0/r,l lG): action: add trace: stack (2 values): 3 2 trace: step 30 (6,0/r,l lG -> 7,0/r,l lR): action: duplicate trace: stack (3 values): 3 3 2 trace: step 31 (7,0/r,l lR -> 10,0/r,l nR): action: push, value 3 trace: stack (4 values): 3 3 3 2 trace: step 32 (10,0/r,l nR -> 12,0/r,l dR): action: push, value 2 trace: stack (5 values): 2 3 3 3 2 trace: step 33 (12,0/r,l dR -> 13,0/r,l lB): action: roll trace: stack (3 values): 2 3 3 trace: step 34 (13,0/r,l lB -> 14,0/r,l lG): action: duplicate trace: stack (4 values): 2 2 3 3 trace: step 35 (14,0/r,l lG -> 15,2/d,r nG): action: push, value 3 trace: stack (5 values): 3 2 2 3 3 trace: step 36 (15,2/d,r nG -> 15,3/d,r dG): action: push, value 1 trace: stack (6 values): 1 3 2 2 3 3 trace: step 37 (15,3/d,r dG -> 14,3/l,l lR): action: roll trace: stack (4 values): 2 3 2 3 trace: step 38 (14,3/l,l lR -> 13,1/l,r lC): action: greater trace: stack (3 values): 1 2 3 trace: step 39 (13,1/l,r lC -> 11,1/l,r nC): action: push, value 3 trace: stack (4 values): 3 1 2 3 trace: step 40 (11,1/l,r nC -> 10,1/l,r lB): action: multiply trace: stack (3 values): 3 2 3 trace: step 41 (10,1/l,r lB -> 9,1/l,r nY): action: pointer trace: stack (2 values): 2 3 trace: white cell(s) crossed - continuing with no command at 9,3... trace: step 42 (9,1/d,r nY -> 9,3/d,l nR):
nany way." Does that mean we can assumento be saved in a variable? \$\endgroup\$nany way. You can save it in a variable, but it must not be hardcoded. \$\endgroup\$