Microsoft SQL Server Connector Guide

The Microsoft SQL Server connector lets Tealfabric workflows run parameterized SQL queries against SQL Server databases. It is commonly used for operational data writes, reporting lookups, and workflow decisions based on relational data.

Document information
FieldValue
Canonical URL/docs/04_connecting-systems/connectors/m/microsoft-sql
Version (published date)2026-05-08
Tagsconnectors, reference, microsoft-sql
Connector IDmicrosoft-sql-1.0.0

Microsoft SQL connector flow showing secure SQL Server authentication, parameterized query execution, and workflow-driven database automation.

Configuration and connection setup

Configure the connector with your SQL Server host, credentials, and database name so workflows can open trusted connections consistently. In production, pair this with encrypted transport and least-privilege database roles.

Required values are host, username, password, and database_name. Optional values include port, ssl_mode, ssl_ca_pem, and timeout_seconds (defaults to 30). After setup, run test to verify connectivity before running scheduled jobs. The test operation validates required configuration fields; other operations defer to SQL Server connection errors when configuration is incomplete.

Use ssl_mode: disable when non-encrypted transport is explicitly permitted.
Use ssl_mode: require for encrypted transport without certificate verification.
Use ssl_mode: verify-ca or ssl_mode: verify-full with ssl_ca_pem to validate the SQL Server TLS certificate chain.

Write records with send

Use send for INSERT, UPDATE, and DELETE statements. Keep queries parameterized using ? placeholders to prevent injection risks and make workflow behavior deterministic.

const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";

async function insertOrderAudit(integrationId: string) {
  const response = await fetch(`${baseUrl}/integrations/${encodeURIComponent(integrationId)}/execute`, {
    method: "POST",
    headers: {
      "X-API-Key": apiKey,
      "X-Tenant-ID": tenantId,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      operation: "send",
      query: "INSERT INTO order_audit (order_id, status, processed_at) VALUES (?, ?, GETUTCDATE())",
      params: ["ORD-10492", "processed"]
    }),
  });
  if (!response.ok) throw new Error(`Request failed: ${response.status}`);
  return response.json();
}
curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
  -H "X-API-Key: <API_KEY>" \
  -H "X-Tenant-ID: <TENANT_ID>" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "send",
    "query": "INSERT INTO order_audit (order_id, status, processed_at) VALUES (?, ?, GETUTCDATE())",
    "params": ["ORD-10492", "processed"]
  }'
{
  "success": true,
  "data": {
    "message_count": 1,
    "rows_affected": 1
  }
}

Read records with receive

Use receive for SELECT statements that feed downstream workflow logic. Keep result windows bounded with SQL filters and TOP clauses when working with large tables.

const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";

async function fetchRecentOrders(integrationId: string) {
  const response = await fetch(`${baseUrl}/integrations/${encodeURIComponent(integrationId)}/execute`, {
    method: "POST",
    headers: {
      "X-API-Key": apiKey,
      "X-Tenant-ID": tenantId,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      operation: "receive",
      query: "SELECT TOP 20 order_id, status, processed_at FROM order_audit WHERE status = ? ORDER BY processed_at DESC",
      params: ["processed"]
    }),
  });
  if (!response.ok) throw new Error(`Request failed: ${response.status}`);
  return response.json();
}
curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
  -H "X-API-Key: <API_KEY>" \
  -H "X-Tenant-ID: <TENANT_ID>" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "receive",
    "query": "SELECT TOP 20 order_id, status, processed_at FROM order_audit WHERE status = ? ORDER BY processed_at DESC",
    "params": ["processed"]
  }'
{
  "success": true,
  "data": {
    "message_count": 1,
    "data": [
      {
        "order_id": "ORD-10492",
        "status": "processed",
        "processed_at": "2026-05-08T15:32:18Z"
      }
    ],
    "total_size": 1
  }
}

Bidirectional SQL with sync

Use sync when a workflow needs both a write leg (outbound) and a read leg (inbound) in one call. Each leg uses the same callData shape as send or receive. Empty or omitted legs are skipped.

{
  "operation": "sync",
  "outbound": {
    "query": "UPDATE order_audit SET status = ? WHERE order_id = ?",
    "params": ["shipped", "ORD-10492"]
  },
  "inbound": {
    "query": "SELECT order_id, status FROM order_audit WHERE order_id = ?",
    "params": ["ORD-10492"]
  }
}
{
  "success": true,
  "data": {
    "message_count": 2,
    "results": {
      "outbound": {
        "success": true,
        "message_count": 1,
        "rows_affected": 1
      },
      "inbound": {
        "success": true,
        "message_count": 1,
        "data": [{ "order_id": "ORD-10492", "status": "shipped" }],
        "total_size": 1
      }
    }
  }
}

Transactional batches with batch

Use batch to run multiple SQL statements in one transaction. All statements commit only when every entry succeeds; otherwise the transaction rolls back. Each entry defaults to operation: "send"; set operation: "receive" to return row data.

{
  "operation": "batch",
  "queries": [
    {
      "query": "INSERT INTO order_audit (order_id, status) VALUES (?, ?)",
      "params": ["ORD-10500", "pending"]
    },
    {
      "operation": "receive",
      "query": "SELECT order_id, status FROM order_audit WHERE order_id = ?",
      "params": ["ORD-10500"]
    }
  ]
}

Test connectivity with test

Run test with no callData to validate configuration and confirm SQL Server connectivity. On success the connector returns server database and user details.

{
  "success": true,
  "data": {
    "message": "Microsoft SQL Server connection test successful",
    "details": {
      "host": "sql.example.com",
      "port": 1433,
      "database": "orders",
      "user": "tf_connector"
    }
  }
}

Reliability guidance

Most production issues come from connectivity settings, missing SQL Server drivers, or permission gaps on target tables. Validate credentials with test, confirm driver availability, and grant least-privilege table access for connector users.

For stable performance, use parameterized SQL everywhere, wrap related writes in batch transactions, and cap result sizes in read queries. These controls keep SQL-backed workflows secure and predictable.

Additional resources