On this page
Database pgsql

PostgreSQL (pgsql)

Query and interact with an external PostgreSQL database using the pgsql keyword in JavaScript scripts.

Syntax
await pgsql.query(sql, [params])

PostgreSQL (pgsql)

When PostgreSQL is configured in your bot settings, the global pgsql object provides direct access to a PostgreSQL connection pool powered by pg.

Syntax

// Run a query
const result = await pgsql.query(sqlText, paramsArray);

// Acquire a dedicated client (e.g. for transactions)
const client = await pgsql.connect();

Methods & Properties

Name Type Description
pgsql.query(text, [params]) Method Executes a parameterized SQL query and returns { rows, rowCount, fields }.
pgsql.connect() Method Acquires a client connection from the pool. Must be released with client.release().
pgsql.pool Property Direct reference to the underlying pg.Pool instance.

Examples

1. Initialize Tables

await pgsql.query(`
  CREATE TABLE IF NOT EXISTS user_levels (
    user_id VARCHAR(32) PRIMARY KEY,
    guild_id VARCHAR(32) NOT NULL,
    xp BIGINT DEFAULT 0,
    level INT DEFAULT 1,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  );
`);

2. Leveling & XP Tracking (Discord Message Event)

const userId = message.author.id;
const guildId = message.guild.id;

// Upsert user XP with parameterized query
const res = await pgsql.query(`
  INSERT INTO user_levels (user_id, guild_id, xp, level)
  VALUES ($1, $2, 10, 1)
  ON CONFLICT (user_id)
  DO UPDATE SET xp = user_levels.xp + 10, updated_at = NOW()
  RETURNING xp, level;
`, [userId, guildId]);

const currentXp = res.rows[0].xp;
console.log(`User ${message.author.username} now has ${currentXp} XP!`);

3. Server Leaderboard Slash Command

const topUsers = await pgsql.query(`
  SELECT user_id, xp, level
  FROM user_levels
  WHERE guild_id = $1
  ORDER BY xp DESC
  LIMIT 10;
`, [interaction.guild.id]);

const description = topUsers.rows.map((row, index) => {
  return `**#${index + 1}** <@${row.user_id}> — Level ${row.level} (${row.xp} XP)`;
}).join('\n');

await interaction.reply({
  embeds: [{
    title: `🏆 Leaderboard — ${interaction.guild.name}`,
    description: description || 'No data yet.',
    color: 0x5865F2,
  }],
});

4. Transactions

const client = await pgsql.connect();
try {
  await client.query('BEGIN');
  await client.query('UPDATE accounts SET balance = balance - 100 WHERE id = $1', [senderId]);
  await client.query('UPDATE accounts SET balance = balance + 100 WHERE id = $2', [recipientId]);
  await client.query('COMMIT');
} catch (err) {
  await client.query('ROLLBACK');
  throw err;
} finally {
  client.release();
}

Security Best Practice

Always use parameterized placeholders ($1, $2, etc.) instead of string concatenation to prevent SQL injection vulnerabilities.