SQL on FHIR
2.1.0-pre - release International flag

SQL on FHIR, published by SQL on FHIR Working Group. This guide is not an authorized publication; it is the continuous build for version 2.1.0-pre built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/FHIR/sql-on-fhir-v2/ and changes regularly. See the Directory of published versions

OperationDefinition: SQLQuery Run

Official URL: http://sql-on-fhir.org/OperationDefinition/$sqlquery-run Version: 2.1.0-pre
Active as of 2026-03-31 Computable Name: SQLQueryRun

Execute a SQLQuery Library against ViewDefinition tables.

Execute a SQLQuery Library against ViewDefinition tables synchronously.

Use Cases:

  • Run ad-hoc analytics queries
  • Interactive query development and testing
  • Real-time data retrieval with parameters

Endpoints:

Level Endpoint Query Source
System POST [base]/$sqlquery-run queryReference or queryResource
Type POST [base]/Library/$sqlquery-run queryReference or queryResource
Instance POST [base]/Library/[id]/$sqlquery-run The Library instance

Execution Flow:

  1. Resolve ViewDefinitions from relatedArtifact
  2. Materialize each ViewDefinition as a table
  3. Bind parameters values to SQL placeholders
  4. Execute SQL query
  5. Return results in requested format (Binary for flat formats, Parameters for _format=fhir)

Implementations MUST ensure parameter values are safely bound to queries and not subject to SQL injection. Use parameterized queries or equivalent safe binding mechanisms where available. Simple string interpolation MUST NOT be used to implement parameter binding.

URL: [base]/$sqlquery-run

URL: [base]/Library/$sqlquery-run

URL: [base]/Library/[id]/$sqlquery-run

Parameters

UseNameScopeCardinalityTypeBindingDocumentation
IN_formatsystem, type, instance1..1codeSQLQuery Run Output Format Codes (Extensible)

Output format for the result (json, ndjson, csv, parquet, fhir). Use fhir to return results as a FHIR Parameters resource.

INheadersystem, type, instance0..1boolean

Include CSV headers (default true). Applies only when csv output is requested.

INqueryReferencesystem, type0..1Reference

Reference to a SQLQuery Library stored on the server.

INqueryResourcesystem, type0..1https://sql-on-fhir.org/ig/StructureDefinition/SQLQuery

Inline SQLQuery Library resource to execute.

INparameterssystem, type, instance0..1Parameters

Input parameters for the query. Parameters are bound by name to parameters declared in the SQLQuery Library (Library.parameter.name). Parameter types are mapped using the appropriate value[x] type matching the declared parameter type.

INsourcesystem, type, instance0..1string

External data source containing the ViewDefinition tables.

OUTreturn1..1Binary | Parameters

Query results. Returns Binary for flat formats (csv, json, ndjson, parquet) or Parameters for _format=fhir.

Notes:

Examples

Instance-Level (Library on Server)

When the SQLQuery Library is stored on the server, invoke directly on the instance:

POST /Library/patient-bp-query/$sqlquery-run HTTP/1.1
Content-Type: application/fhir+json

{
  "resourceType": "Parameters",
  "parameter": [
    { "name": "_format", "valueCode": "csv" },
    { "name": "parameters", "resource": {
      "resourceType": "Parameters",
      "parameter": [
        { "name": "patient_id", "valueString": "Patient/123" },
        { "name": "from_date", "valueDate": "2024-01-01" }
      ]
    }}
  ]
}

Type-Level with Reference

Reference a stored Library by URL or relative reference:

POST /Library/$sqlquery-run HTTP/1.1
Content-Type: application/fhir+json

{
  "resourceType": "Parameters",
  "parameter": [
    { "name": "_format", "valueCode": "json" },
    { "name": "queryReference", "valueReference": {
      "reference": "Library/patient-bp-query"
    }},
    { "name": "parameters", "resource": {
      "resourceType": "Parameters",
      "parameter": [
        { "name": "patient_id", "valueString": "Patient/123" }
      ]
    }}
  ]
}

Type-Level with Inline Resource

Pass the SQLQuery Library inline for ad-hoc queries:

POST /Library/$sqlquery-run HTTP/1.1
Content-Type: application/fhir+json

{
  "resourceType": "Parameters",
  "parameter": [
    { "name": "_format", "valueCode": "ndjson" },
    { "name": "queryResource", "resource": {
      "resourceType": "Library",
      "meta": { "profile": ["https://sql-on-fhir.org/ig/StructureDefinition/SQLQuery"] },
      "type": { "coding": [{ "system": "https://sql-on-fhir.org/ig/CodeSystem/LibraryTypesCodes", "code": "sql-query" }] },
      "status": "active",
      "relatedArtifact": [
        { "type": "depends-on", "resource": "https://example.org/ViewDefinition/patient_view", "label": "p" }
      ],
      "content": [{
        "contentType": "application/sql",
        "data": "U0VMRUNUIHAuaWQsIHAubmFtZSBGUk9NIHAgV0hFUkUgcC5hY3RpdmUgPSB0cnVl",
        "extension": [{
          "url": "https://sql-on-fhir.org/ig/StructureDefinition/sql-text",
          "valueString": "SELECT p.id, p.name FROM p WHERE p.active = true"
        }]
      }]
    }}
  ]
}

System-Level

Invoke at the server base without a resource type. This is useful when the server supports SQLQuery Libraries but does not expose them as FHIR Library resources:

POST /$sqlquery-run HTTP/1.1
Content-Type: application/fhir+json

{
  "resourceType": "Parameters",
  "parameter": [
    { "name": "_format", "valueCode": "csv" },
    { "name": "queryReference", "valueReference": {
      "reference": "Library/patient-bp-query"
    }},
    { "name": "parameter", "part": [
      { "name": "name", "valueString": "patient_id" },
      { "name": "value", "valueString": "Patient/123" }
    ]}
  ]
}

Response

For flat formats (csv, json, ndjson, parquet), the response is a Binary:

HTTP/1.1 200 OK
Content-Type: text/csv

patient_id,systolic,effective_date
Patient/123,120,2024-01-15
Patient/123,118,2024-02-20

FHIR Format Response

When _format=fhir, the response is a FHIR Parameters resource with each row as a repeating row parameter.

POST /Library/patient-bp-query/$sqlquery-run HTTP/1.1
Content-Type: application/fhir+json

{
  "resourceType": "Parameters",
  "parameter": [
    { "name": "_format", "valueCode": "fhir" },
    { "name": "parameters", "resource": {
      "resourceType": "Parameters",
      "parameter": [
        { "name": "patient_id", "valueString": "Patient/123" }
      ]
    }}
  ]
}

Response:

{
  "resourceType": "Parameters",
  "parameter": [
    { "name": "row", "part": [
      { "name": "patient_id", "valueString": "Patient/123" },
      { "name": "systolic", "valueInteger": 120 },
      { "name": "effective_date", "valueDate": "2024-01-15" }
    ]},
    { "name": "row", "part": [
      { "name": "patient_id", "valueString": "Patient/123" },
      { "name": "systolic", "valueInteger": 118 },
      { "name": "effective_date", "valueDate": "2024-02-20" }
    ]}
  ]
}

When a query returns zero rows, the response is a Parameters resource with no parameter elements:

{
  "resourceType": "Parameters"
}

SQL to FHIR type mapping

When _format=fhir, each result column must be encoded using a FHIR value[x] type. The following table defines the mapping from ISO/IEC 9075 SQL types to FHIR parameter value types.

ISO/IEC 9075 SQL type FHIR value type
BOOLEAN valueBoolean
TINYINT, SMALLINT, INT, INTEGER valueInteger
BIGINT valueInteger64
DECIMAL, NUMERIC valueDecimal
REAL valueDecimal
FLOAT, DOUBLE PRECISION valueDecimal
CHARACTER, CHARACTER VARYING, CHARACTER LARGE OBJECT valueString
BINARY, BINARY VARYING, BINARY LARGE OBJECT valueBase64Binary
DATE valueDate
TIME, TIME WITH TIME ZONE valueTime
TIMESTAMP valueDateTime
TIMESTAMP WITH TIME ZONE valueInstant

SQL NULL values are represented by omitting the corresponding part from the row parameter.

Conversion of REAL, FLOAT, and DOUBLE PRECISION values to valueDecimal may introduce representation artefacts due to the difference between binary and decimal floating point.

TIMESTAMP WITH TIME ZONE values may carry sub-millisecond precision (e.g. microseconds), but FHIR instant supports at most millisecond precision. Implementations SHOULD round to the nearest millisecond when converting to valueInstant.

TIMESTAMP (without time zone) values are converted to valueDateTime without a timezone offset. FHIR dateTime permits values with or without a timezone, so the absence of timezone information is preserved rather than trying to infer a time zone.

ISO/IEC 9075 types not listed in this table (such as INTERVAL, ARRAY, XML, ROW, and MULTISET) are not supported. If a query produces a result column with an unsupported type, the server MUST return a 422 Unprocessable Entity error. Query authors can work around this by casting unsupported types to a supported type within the SQL query.

Parameter Passing

Query parameters are passed as a nested Parameters resource, following the same pattern as the CQL $evaluate operation. Each parameter in the Parameters resource is bound by name to a parameter declared in the SQLQuery Library (Library.parameter).

Use the appropriate value[x] type matching the Library’s declared parameter type:

Library.parameter.type Parameters.parameter value
string valueString
integer valueInteger
date valueDate
dateTime valueDateTime
boolean valueBoolean
decimal valueDecimal

Error Handling

Status Condition
400 Bad Request Missing required parameter, unknown parameter name, or value type mismatch
404 Not Found Library or ViewDefinition not found
422 Unprocessable Entity SQL execution error, or unsupported SQL column type when using _format=fhir (see type mapping)