Data rules validate the records in your study datasets. They are written in PQL (Pinnacle Query Language), a custom language based on SQL with added shorthand that simplifies writing validation rules. PQL is used for rules with Target = Data only.
How a Data rule logic works
A PQL expression is evaluated against every record in the dataset being validated and describes which records fail. In the rule's Logic section (set the Language to PQL) you fill in two boxes, referred to here as the Query and the Filter:
Box (label in the UI) | Required? | What it does |
Query ("Raise an issue when the following criteria is met") | Required | The condition that identifies a failing record. Records matching it become findings. |
Filter ("Only execute for records that match the following criteria") | Optional | Limits which records the Query is checked against. |
Note Logic only describes which records fail. The rest of the rule is set in the other fields on the Properties tab (Rule ID, Message, Description, and Message Type) and on the Assignments tab (which standards and versions the rule runs against).
The data you can reference
Reference | Meaning |
Variable in the current dataset | A bare variable name, e.g. |
Generic / placeholder variable | A |
Data supplement variable | A variable P21 automatically merges onto every dataset (chiefly subject-level |
Note A dot-value such as DM.RFSTDTC only works for data supplement variables: the variables P21 automatically adds to every dataset (chiefly subject-level DM variables and TS parameters). It is not a general way to join another dataset. A reference to anything that isn't a data supplement (for example SUPPDM.QNAM, or any variable on a custom standard) won't resolve, and because no error is raised, the rule can pass without checking what you intended. The complete list is in the Data supplement variables section at the bottom of this article.
Expression types
PQL expressions fall into three types.
Basic expressions
Format: PRIMARY_VALUE COMPARATOR COMPARATIVE_VALUE (a variable, an operator, and the value it's compared to).
AESER = 'Y'
DOSE > 0
VISITNUM IS NOT NULL
IN expressions
Compare one or more values against several comparative values with IN / NOT IN. Comparative values can be a tuple of variables or a list of strings.
ACTARMCD NOT IN ('SCRNFAIL', 'NOTASSGN', 'UNPLAN', 'NOTTRT')
Compound expressions
Combine Basic or IN expressions with AND / OR.
SSSTRESC IN ('DEAD', '死亡') AND USUBJID IS NOT NULL
AESER = 'Y' AND AEOUT IS NULL
Value types
Type | Notes & example |
Variable reference | Standard ( |
Tuple | Multiple values compared together: |
List | Comma-separated strings in parentheses: |
String | Text in single quotes: |
Number | Numeric values used in comparisons: |
NULL | Absence of a value: |
Comparators and operators
Valid comparators: <, <=, >, >=, =, !=, <>, IS, IS NOT. (!= and <> are equivalent; IS/IS NOT are used with NULL.) Membership operators: IN, NOT IN.
Functions
Function | What it does & example |
| Flags duplicate values. |
| Flags values that should match within a group but don't. |
| Tests a value against a regular expression; matches when the whole value matches the pattern. Negate with |
GROUP
A special function used with DUPLICATE and MISMATCH to group records (like SQL's GROUP BY). You can group by more than one variable by separating them with commas.
DUPLICATE(USUBJID) GROUP(STUDYID)
MISMATCH(--ELTM) GROUP(--TPT, --TPTREF, VISITNUM)
Using REGEXP
REGEXP(variable, 'pattern') is true when the variable matches the pattern, and NOT REGEXP(variable, 'pattern') is true when the variable does not match the pattern. A few things to know:
Whole-value match.
REGEXPchecks the value from start to end, not just part of it. For example,REGEXP(--ORRES, '[0-9]+')matches'123'but not'12 mg', because the whole value has to be digits. (Since the match already covers the whole value, you don't need^or$anchors.) To match a value that merely contains your text, add.*to both ends:REGEXP(VISIT, '.*SCREEN.*')matches anyVISITthat containsSCREEN, such as'UNSCHEDULED SCREEN'.Blank values. A null or empty value never matches a pattern, so
NOT REGEXPis true for blank rows. Add anIS NOT NULLcheck in the Filter if you don't want to flag those.Backslashes. Write backslashes directly, for example
\dfor a digit or\.for a literal dot (not\\dor\\.).
Flags
Flag | What it does & example |
| Placed before a comparator to make the comparison case-insensitive. |
| Placed before a tuple so the comparator matches if any variable meets the condition. |
Examples
# | What it checks | Query | Filter |
1 | Serious AEs must have an outcome |
| — |
2 | ARMCD must be a valid value |
| — |
3 | No duplicate subjects within a study |
| — |
4 | Reported result must be a positive integer |
|
|
5 | Flag unscheduled visits |
| — |
6 | AEs must not start before the reference start date |
|
|
7 | Dose must not be negative |
|
|
8 | ARM is not 'Screen Failure' when ARMCD equals 'SCRNFAIL', or vice versa |
|
|
Dates in ISO 8601 format compare correctly as text, so date variables can be compared with <, >, and the other operators (as in Example 6).
Data supplement variables
Data supplement variables
These are the variables a dot-value reference can resolve to. The set depends on the standard type, and they are not available on custom standards. Prefixes like DSMAX/DSMIN indicate which record is used when a subject has several: MAX takes the latest/largest value, MIN the earliest/smallest.
SDTM
Reference | Description |
| Unique subject identifier |
| Description of actual arm |
| Actual arm code |
| Description of planned arm |
| Planned arm code |
| Reason arm and/or actual arm is null |
| Date/time of death |
| Subject death flag |
| Subject reference start date/time |
| Subject reference end date/time |
| Date/time of first study treatment |
| Date/time of last study treatment |
| Date/time of informed consent |
| Date/time of end of participation |
SEND
Reference | Description |
| Unique subject identifier |
| Description of actual arm |
| Actual arm code |
| Description of planned arm |
| Planned arm code |
| Set code |
| Subject reference start date/time |
| Subject reference end date/time |
| Date/time of first study treatment |
| Date/time of last study treatment |
| Date/time of informed consent |
| Date/time of end of participation |
| Subject reference date/time (verify) |
| Subject reference date/time (verify) |
ADaM
Reference | Description |
| Description of planned arm (from ADSL) |
| Planned treatment for period 01 |
| Subject identifier for the study |
| Study identifier |
| Study site identifier |
| Description of actual arm |
| Description of planned arm |
| Reason arm and/or actual arm is null |
| Age |
| Age units |
| Sex |
| Race |
| Ethnicity |
| Subject reference start date/time |
| Subject reference end date/time |