DDS Data Types vs SQL Data Types

  • Home
  • /
  • Blog
  • /
  • DDS Data Types vs SQL Data Types

May 3, 2026

The Mysterious “M” in Your DDS: Naming Conventions vs Keyboard Shifts

This morning I opened a DSPF and spotted what looked like a data type of “M” against a field that smelled numeric. My first thought? “Since when did IBM i add an M type?” Turns out the original developer had a very correct reason for using ‘M’ and I had simply not seen it for so long (shhh… its been decades) and I had completely forgotten about this infrequently used datatype, so it got me digging deeper.

There really is an “M” data-type for number values in DSPF land. Just not where most people expect.

Let’s clear this up once and for all.

DDS Data Types vs SQL Data Types

First, the Naming Convention Trap

In many older AS/400 shops we used prefixes to give fields instant meaning. You still see this everywhere:

  • A# – Alphanumeric
  • N# – Numeric
  • D# – Date
  • M# – Monetary / money amount

So you end up with perfectly normal DDS like this:

M#PRICE      9P 2
M#TAX        7P 2
M#TOTAL     11P 2

The “M#” is just part of the field name. The real data type is still P (packed decimal). No magic M type exists in DDS for physical or logical files.

But Wait – “M” Does Exist in DSPFs

Here’s where it gets fun. In Display Files (DSPF), M is a real thing, it is a keyboard shift attribute.

When you define a field in a DSPF, column 35 (the Usage/Keyboard Shift position in fixed-format DDS) lets you control what the user can actually type. One of those options is M.

M = Numeric-only character shift

This tells the display file: “Only let the user enter these characters”:

  • Digits 0–9
  • Plus sign (+)
  • Minus sign (-)
  • Comma (,)
  • Period (.)
  • Blank spaces

It does not make the field numeric for storage or calculations. The field is still defined as alphanumeric (A). M is purely an input filter.

The Real “M” : Keyboard Shift in DSPFs

In Display Files (DSPF), M is a genuine keyboard shift attribute.

It lives in column 35 (the Usage/Keyboard Shift position in fixed-format DDS) and controls exactly what the user can type into the field.

Valid Keyboard Shifts for Display Files

Here is the official list (IBM last updated 2025):

Keyboard ShiftMeaningData Type Permitted
BlankDefaultAlphabetic only (Character)
AAlphanumeric shiftCharacter
NNumeric shiftCharacter or numeric
SSigned numericNumeric
YNumeric onlyNumeric
WKatakana (Japan only)Character
IInhibit keyboard entryCharacter or numeric
DDigits onlyCharacter or numeric
MNumeric only characterCharacter
FFloating pointNumeric
LDate
TTime
ZTimestamp

Note: Data types J, E, O, and G are for DBCS support. G also handles UTF-16 and UCS-2.

What “M” Actually Does

When you code this:

     A            AMOUNT        15A  B 10  5M

or with keywords:

     A            AMOUNT        15A         B 10  5
     A                                                                CHECK(MF)

The field accepts only digits 0-9, plus, minus, comma, period and spaces. It is still stored as alphanumeric (A). M is purely an input filter, not a numeric data type.

Bonus: DDS Data Types vs SQL Data Types

Because modern IBM i work often mixes DDS and SQL, here is a practical comparison of the most common types.

DDS TypeMeaningTypical Length/FormatSQL EquivalentNotes / Gotchas
AAlphanumeric (Character)Up to 32,766CHAR or VARCHARVARCHAR is usually better in SQL tables
PPacked decimal1-31 digitsDECIMAL(p,s) or NUMERIC(p,s)Most common for money fields
SZoned decimal1-31 digitsDECIMAL(p,s) or NUMERIC(p,s)Less efficient than packed
BBinary1-9 bytesSMALLINT / INTEGER / BIGINTUse SQL integer types instead
FFloating point4 or 8 bytesFLOAT or DOUBLERare on IBM i business apps
LDate10 bytes (ISO)DATEPerfect match
TTime8 bytesTIMEPerfect match
ZTimestamp26 bytesTIMESTAMPPerfect match
GGraphic (DBCS)1-16,383 charactersGRAPHIC or VARGRAPHICFor double-byte languages
J/E/ODBCS open/either/onlyVariesVARGRAPHICMostly legacy

Light programmer humour moment: Mapping a 30-year-old DDS file packed with zoned decimals into a clean SQL table feels like teaching your grandad to use TikTok. Possible, but everyone ends up slightly confused.

Best practice tip: For brand new development, use SQL DDL with proper DECIMAL, DATE and VARCHAR types. Keep DDS for legacy files or when you need tight DSPF/PRTF control.

IBM SQL Data types against equivalent DDS data types

IBM SQL Data types against equivalent DDS data types

Here’s a practical side-by-side comparison of IBM i SQL (Db2 for i) data types versus their DDS equivalents. This focuses on what you’ll actually use when modernizing files or writing new tables on IBM i.

I will try to keep it technical, no fluff, but will probably add a bit of programmer humour because staring at packed decimals for 20 years does that to a man.

Numeric Types

DDS TypeDDS ExampleSQL EquivalentSQL ExampleNotes / Gotchas
Packed (P)7P 2DECIMAL(p,s)DECIMAL(7,2)Packed is the storage-efficient king in DDS. SQL DECIMAL is its direct match. Use this for money , it behaves like a sane accountant.
Zoned/Signed (S)7S 0NUMERIC(p,s)NUMERIC(7,0)Zoned decimal. SQL NUMERIC is the zoned equivalent. Takes more space than packed but displays nicely for humans.
Binary (B)4B 0 or 9B 0 or 18B 0SMALLINT / INTEGER / BIGINTSMALLINT, INTEGER, BIGINTDDS binary is basically the same as SQL integers under the hood. Note: Smallint=4 bytes, Integer=9 digits (4 bytes), Bigint=18 digits (8 bytes).
Float Single (F)9F FLTPCN(*SINGLE)REAL or FLOAT(1-24)REALSingle precision floating point. Use only when you really need scientific notation and don’t mind the precision weirdness.
Float Double (F)17F FLTPCN(*DOUBLE)DOUBLE or FLOAT(25-53)DOUBLEDouble precision. Same warning as above, but with more digits of “oops”.
n/an/aDECFLOAT(16) or DECFLOAT(34)DECFLOAT(34)No direct DDS equivalent. Decimal floating point, it’s excellent for exact decimal math without rounding surprises. Modern SQL win.

Pro tip: In RPG when you externally describe an SQL table, SMALLINT becomes 4B 0, INTEGER becomes 9B 0, and BIGINT becomes 20I 0 (with EXTBININT(*YES) it gets friendlier). The precompiler has opinions.

Character & Binary String Types

DDS TypeDDS ExampleSQL EquivalentSQL ExampleNotes
Character (A)10ACHAR(n)CHAR(10)Fixed length. Padded with blanks. Classic.
Variable Char (A + VARLEN)50A VARLENVARCHAR(n)VARCHAR(50)Variable length. Saves space and is the modern default.
Hex (H)10HCHAR(n) FOR BIT DATACHAR(10) FOR BIT DATABinary character data.
Binary (5)10 5 (binary char)BINARY(n)BINARY(10)Fixed binary.
Var Binary10 5 VARLENVARBINARY(n)VARBINARY(10)Variable binary.

Date / Time Types (The Good Ones)

DDSDDS ExampleSQLSQL ExampleNotes
Date (L)LDATEDATEISO date by default. Beautiful.
Time (T)TTIMETIMETime.
Timestamp (Z)ZTIMESTAMPTIMESTAMPTimestamp with microsecond precision.

SQL bonus: You get TIMESTAMPDIFF, CURRENT DATE, etc. DDS just sits there looking pretty.

Large Objects & Special Types

DDSSQL EquivalentNotes
n/aCLOB(n)Character Large Object. Up to 2GB. No DDS equivalent (as far as I am aware) this is why we love SQL.
n/aBLOB(n)Binary Large Object.
n/aDBCLOB(n)Double-byte character LOB.
n/aDATALINKStill exists but rarely used. Links to external files.
Graphic (G)GRAPHIC / VARGRAPHICUCS-2 / Unicode. Use CCSID(13488) for proper Unicode.
n/aXML, JSON (via functions)Modern SQL goodies DDS never dreamed of.

Quick Mapping Summary (Most Common)

  • PackedDECIMAL (your go-to for business numbers)
  • ZonedNUMERIC
  • BinarySMALLINT/INTEGER/BIGINT
  • ACHAR / VARCHAR
  • L/T/ZDATE/TIME/TIMESTAMP
  • H/5BINARY types

Modern advice from the IBM-i battle fields: If you’re creating anything new, use SQL DDL (CREATE TABLE). It gives you constraints, identity columns, long names, better performance with SQE, and future-proofing. DDS is still fine for legacy stuff and display/printer files (SQL can’t do those).

You can even use the QSQGNDDL API to auto-generate DDL from your existing DDS files, IBM literally hands you the conversion script.

If you’re creating/modifying/modernizing DSPF then remember:

  • M# in a field name = old naming convention (usually monetary)
  • M in column 35 of a DSPF = keyboard shift for numeric-only character input
  • M does not change the data type, the field is still A unless you define it otherwise
  • Always check the column position in fixed-format DDS
  • Know your DDS-to-SQL mappings or you will spend hours chasing data format bugs

Legacy code is full of these little time bombs. One developer from years ago uses M# for money fields, another sticks an M in the keyboard shift column, and suddenly the next person is convinced IBM quietly added a new data type while we were not looking.

Got any favourite old-school IBM i naming conventions, quirky keyboard shifts, or painful DDS-to-SQL migration stories? Drop them in the comments. I love collecting these war stories.

Happy coding on the ‘i!

NickLitten


IBM i Software Developer, Digital Dad, AS400 Anarchist, RPG Modernizer, Shameless Trekkie, Belligerent Nerd, Englishman Abroad and Passionate Eater of Cheese and Biscuits.

Nick Litten Dot Com is a mixture of blog posts that can be sometimes serious, frequently playful and probably down-right pointless all in the space of a day.

Enjoy your stay, feel free to comment and remember: If at first you don't succeed then skydiving probably isn't a hobby you should look into.

Nick Litten

related posts:

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

Subscribe NOW
7-day free trial

Take This Course with ALL ACCESS

Unlock your Learning Potential with instant access to every course and all new courses as they are released.
 [ For Serious Software Developers only ]

Online Learning for IBM i Software Technology Professionals

“The more that you read, the more things you will know. The more that you learn, the more places you’ll go.” – Dr. Seuss

>