docs(validations): a range rule compares in SAS's own order

A range rule keys both the cell value and its own value into the order SAS uses
for a numeric variable: every missing below every non-missing value, and the
missing values ordered ._ then the regular missing then .A through .Z. So a range
can be written in special missings and mean what SAS means by it - MINVAL .A with
MAXVAL .C accepts .B and rejects .D - and the numeric cases follow from the same
order: a missing fails a numeric MINVAL and passes a numeric MAXVAL, and a number
sits above every missing.

Replaces the "a range rule ignores a missing value" wording, which described the
previous take's behaviour rather than SAS's.
This commit is contained in:
dc
2026-09-23 21:27:57 +00:00
parent 66c48a4cc7
commit 83641a204f
+6 -4
View File
@@ -56,8 +56,8 @@ The rules treat a special missing as a value for some checks and as a missing va
|Rule|What happens to a special missing| |Rule|What happens to a special missing|
|---|---| |---|---|
|NOTNULL|Fails. A special missing is a missing value, so a NOT NULL (or primary key) constraint rejects it, and a real SAS NOT NULL constraint on the target table rejects it too.| |NOTNULL|Fails. A special missing is a missing value, so a NOT NULL (or primary key) constraint rejects it, and a real SAS NOT NULL constraint on the target table rejects it too.|
|MINVAL|Passes. A missing value is not a number, so a minimum does not apply to it - use NOTNULL if the column must be populated. A real number below the minimum still fails.| |MINVAL|Fails if the minimum is a number - a missing sorts below every number, so it is below any numeric floor. A minimum that is itself a special missing is compared in the order the missing values have among themselves, and can accept one.|
|MAXVAL|Passes, for the same reason. A real number above the maximum still fails.| |MAXVAL|Passes - a missing sorts below every number, so it is below any numeric ceiling. A ceiling that is itself a special missing is compared in the missing values' own order, and can reject one.|
|CASE|Not applicable - it is a character rule.| |CASE|Not applicable - it is a character rule.|
|ROUND|Ignored - ROUND only rounds values that are numbers, so a special missing is left as typed.| |ROUND|Ignored - ROUND only rounds values that are numbers, so a special missing is left as typed.|
|HARDREGEX / SOFTREGEX|Checked against the pattern like any other value. Unlike blanks and the plain `.`, special missings are **not** exempt. See [Regex Rules](#regex-rules).| |HARDREGEX / SOFTREGEX|Checked against the pattern like any other value. Unlike blanks and the plain `.`, special missings are **not** exempt. See [Regex Rules](#regex-rules).|
@@ -65,11 +65,13 @@ The rules treat a special missing as a value for some checks and as a missing va
|HARDSELECT|Supports special missings - the value is matched against the dropdown list like any other value.| |HARDSELECT|Supports special missings - the value is matched against the dropdown list like any other value.|
|HARDFORMULA / SOFTFORMULA|The formula returns `#VALUE!` for that row instead of a number, and that is what gets submitted.| |HARDFORMULA / SOFTFORMULA|The formula returns `#VALUE!` for that row instead of a number, and that is what gets submitted.|
In short, a special missing is rejected by NOTNULL (and by a primary key column), and a formula returns `#VALUE!` for it. It is fine in a column that carries a range rule, a regex, a dropdown, or ROUND. In short, a special missing is rejected by NOTNULL (and by a primary key column), by a MINVAL whose floor is a number, and a formula returns `#VALUE!` for it. It is fine in a column that carries a MAXVAL, a regex, a dropdown, or ROUND - and it can satisfy a MINVAL when the floor is expressed as a special missing.
A range rule compares in the order SAS itself uses, so a range can be written in special missings and mean what SAS would mean by it. That order puts every missing below every non-missing value, and orders the missing values as `._`, then the regular missing, then `.A` through `.Z`. So `MINVAL .A` with `MAXVAL .C` accepts `.B` and rejects `.D`, and a blank - the regular missing - fails a floor of `.A` because it sorts below it. A number sorts above every missing, so it passes a floor of `.A` and fails a ceiling of `.C`.
A primary key column is treated as NOT NULL whether or not the target table carries a physical constraint, and whether or not MPE_VALIDATIONS has a NOTNULL rule for it - a key identifies the row, so a blank and a special missing are both rejected there. A primary key column is treated as NOT NULL whether or not the target table carries a physical constraint, and whether or not MPE_VALIDATIONS has a NOTNULL rule for it - a key identifies the row, so a blank and a special missing are both rejected there.
One related gotcha: a range rule's own value must be a number. The rule value is compared as a number, so a special missing there leaves nothing for a real value to pass: put one in `MINVAL` and every number in the column fails; put one in `MAXVAL` and every number fails too. A range rule's own value is read as a number when it looks like one and as a missing value when it is a special missing. A value that is neither - a typo such as `..` or `AB` - satisfies nothing, so every cell in the column fails until the rule is corrected.
## Formula Rules ## Formula Rules