Deploy your first customer portal →
SuitePortal/NetSuite ORM

Raw SuiteQL

Execute raw SuiteQL queries when you need full control.

The query builder covers common use cases, but sometimes you need the full power of SuiteQL. The $queryRaw method is your escape hatch.

$queryRaw

const results = await ns.$queryRaw<{ id: string; companyname: string }>(
  "SELECT id, companyname FROM customer WHERE isinactive = 'F' ORDER BY companyname ASC"
);

The type parameter <T> controls the return type — use it to get typed results from your raw queries.

Use Cases

JOINs

SuiteQL supports joins across record types:

const data = await ns.$queryRaw<{
  tranid: string;
  companyname: string;
  total: string;
}>(
  `SELECT t.tranid, c.companyname, t.foreigntotal
   FROM transaction t
   INNER JOIN customer c ON t.entity = c.id
   WHERE t.type = 'CustInvc'
   ORDER BY t.id DESC`
);

Aggregations

const summary = await ns.$queryRaw<{
  entity: string;
  total_invoices: string;
  total_amount: string;
}>(
  `SELECT entity, COUNT(*) AS total_invoices, SUM(foreigntotal) AS total_amount
   FROM transaction
   WHERE type = 'CustInvc'
   GROUP BY entity
   ORDER BY total_amount DESC`
);

Subqueries

const results = await ns.$queryRaw<{ id: string; companyname: string }>(
  `SELECT id, companyname FROM customer
   WHERE id IN (
     SELECT entity FROM transaction WHERE type = 'SalesOrd'
   )`
);

Using the Connector Directly

For advanced use cases (pagination, retry control), you can use the connector directly:

import { NetSuiteClient, executeSuiteQL, executeSuiteQLPaginated } from 'suiteportal';

const client = new NetSuiteClient(config);

// Single page
const result = await executeSuiteQL(client, 'SELECT id FROM customer', {
  limit: 100,
  offset: 0,
});

// Auto-paginate through all results
const allRows = await executeSuiteQLPaginated(client, 'SELECT id FROM customer', {
  pageSize: 1000,
  maxRows: 10000,
});

On this page