SQL Server

The SQL Server connector (type sqlserver; mssql, sql_server, and sql-server are accepted aliases) translates GQL queries into T-SQL. It requires a mapping file that maps graph patterns to relational tables — the same format as every other SQL backend.

The driver is tiberius, a pure-Rust implementation of the TDS wire protocol. No ODBC driver or system packages are required at build or runtime.

SQL Server is available in multi mode only — there is no standalone CONNECTOR_TYPE=sqlserver environment mode yet. You register it at runtime with ADD CONNECTOR … TYPE sqlserver, as shown below.

1. Start SQL Server

docker network create memgql-net
 
docker run -d --rm \
    --name sqlserver-dev \
    --network memgql-net \
    -p 1433:1433 \
    --env ACCEPT_EULA=Y \
    --env MSSQL_SA_PASSWORD='Memgraph!2024' \
    --env MSSQL_PID=Developer \
    mcr.microsoft.com/mssql/server:2022-latest

SQL Server takes ~20 seconds to accept connections. Then create a working database:

docker exec sqlserver-dev /opt/mssql-tools18/bin/sqlcmd \
    -S localhost -U sa -P 'Memgraph!2024' -C \
    -Q "IF DB_ID('test') IS NULL CREATE DATABASE [test]"

2. Seed data

docker exec -i sqlserver-dev /opt/mssql-tools18/bin/sqlcmd \
    -S localhost -U sa -P 'Memgraph!2024' -C -b -d test << 'SQL'
CREATE TABLE persons (
    id   INT IDENTITY(1,1) PRIMARY KEY,
    name NVARCHAR(255) NOT NULL,
    age  INT
);
CREATE TABLE companies (
    id   INT IDENTITY(1,1) PRIMARY KEY,
    name NVARCHAR(255) NOT NULL
);
CREATE TABLE knows (
    id      INT IDENTITY(1,1) PRIMARY KEY,
    from_id INT NOT NULL REFERENCES persons(id),
    to_id   INT NOT NULL REFERENCES persons(id)
);
CREATE TABLE works_at (
    id         INT IDENTITY(1,1) PRIMARY KEY,
    person_id  INT NOT NULL REFERENCES persons(id),
    company_id INT NOT NULL REFERENCES companies(id)
);
 
INSERT INTO persons (name, age) VALUES ('Alice', 30), ('Bob', 25);
INSERT INTO companies (name) VALUES ('Acme Corp');
INSERT INTO knows (from_id, to_id) VALUES (1, 2);
INSERT INTO works_at (person_id, company_id) VALUES (1, 1);
GO
SQL

3. Write the mapping

Save as mapping.json — the standard mapping format. Declare every property you plan to query: in multi mode the mapping is also the routing schema, and a property that isn’t declared is a routing error, not a passthrough.

{
  "nodes": [
    {
      "label": "Person", "table": "persons", "id_column": "id",
      "properties": { "name": "name", "age": "age" }
    },
    {
      "label": "Company", "table": "companies", "id_column": "id",
      "properties": { "name": "name" }
    }
  ],
  "edges": [
    {
      "rel_type": "KNOWS", "table": "knows", "id_column": "id",
      "source_column": "from_id", "target_column": "to_id",
      "source_label": "Person", "target_label": "Person"
    },
    {
      "rel_type": "WORKS_AT", "table": "works_at", "id_column": "id",
      "source_column": "person_id", "target_column": "company_id",
      "source_label": "Person", "target_label": "Company"
    }
  ]
}

4. Start MemGQL in multi mode

docker run --rm \
    --name memgql \
    --network memgql-net \
    --stop-timeout 2 \
    -p 7688:7688 \
    --env CONNECTOR_TYPE=multi \
    --env BOLT_LISTEN_ADDR=0.0.0.0:7688 \
    -v ./mapping.json:/data/mapping.json \
    memgraph/memgql:latest

5. Connect and register the backend

mgconsole --port 7688
ADD MAPPING social FROM '/data/mapping.json';
ADD CONNECTOR ss TYPE sqlserver
    URI 'Server=sqlserver-dev,1433;Database=test;User Id=sa;Password=Memgraph!2024;TrustServerCertificate=true'
    MAPPING social;
CONNECT ss AS ss_conn;

The URI is an ADO-style connection string (Server=<host>,<port>;Database=<db>;User Id=<user>;Password=<pass>;…).

6. Query

MATCH (p:Person) RETURN p.name, p.age;
MATCH (p:Person)-[:WORKS_AT]->(c:Company) RETURN p.name, c.name;
MATCH (a:Person)-[:KNOWS]->(b:Person) RETURN a.name, b.name;

Dialect notes

  • Positional bind parameters use SQL Server’s native @P1, @P2, … form.
  • LIMIT n / SKIP m render as ORDER BY … OFFSET m ROWS FETCH NEXT n ROWS ONLY; when the query has no ORDER BY, a neutral ORDER BY (SELECT NULL) is synthesized because T-SQL requires one for OFFSET/FETCH.
  • Booleans are emitted as BIT (1/0).
  • char_length() / length() on a column translate to T-SQL LEN().
  • No INSERT … RETURNING — SQL Server’s OUTPUT clause is used only when the caller needs the auto-generated key.

Known limitations

  • Variable-length paths — quantified path patterns ((){1,3}) and trail semantics are not available on SQL Server yet and return an actionable error. Use a bounded fixed-hop chain or a Cypher backend.
  • collect() is not available — there is no portable array aggregate in the T-SQL surface MemGQL emits yet; the query fails with the backend’s error.
  • Map projections (RETURN n {.a, .b}) currently return NULL instead of a map (no error is raised) — don’t rely on them on this backend.
  • INSERT … RETURN executes the insert but returns the affected-row count instead of the projected values.

For connector configuration, see Reference.