Skip to content
bel-crm-sql-rules logo

BEL CRM SQL Rules

bel-crm-sql-rules

CRITICAL: PostgreSQL MCP Server SQL limitations and correct patterns. This skill MUST be consulted before writing any SQL for the CRM database. Documents what works and what DOES NOT work with mcp__postgresql__ tools.

SKILL.md

Full skill instructions

BEL CRM SQL Rules

CRITICAL: PostgreSQL MCP Server Limitations

The mcp__postgresql__ tools have specific limitations. Violating these rules causes SQL errors.


FORBIDDEN SQL Patterns (WILL FAIL)

1. RETURNING Clause - FORBIDDEN

-- FORBIDDEN - WILL FAIL with syntax error
INSERT INTO person (name, email) VALUES ('John', '[email protected]') RETURNING id;

-- FORBIDDEN - WILL FAIL
UPDATE company_site SET name = 'New Name' WHERE id = 1 RETURNING *;

-- FORBIDDEN - WILL FAIL
DELETE FROM event WHERE id = 5 RETURNING id;

Why: The write_query tool parses SQL and rejects RETURNING clauses.

2. ON CONFLICT (UPSERT) - FORBIDDEN

-- FORBIDDEN - WILL FAIL with "Only INSERT, UPDATE, or DELETE operations are allowed"
INSERT INTO company_site (name) VALUES ('Acme')
ON CONFLICT (name) DO UPDATE SET updated_at = CURRENT_TIMESTAMP;

-- FORBIDDEN - Even if column HAD a unique constraint
INSERT INTO person (email) VALUES ('[email protected]')
ON CONFLICT (email) DO NOTHING;

Why: The write_query tool does not support ON CONFLICT syntax.

Additional Note: The CRM tables do NOT have UNIQUE constraints on name columns anyway!

  • company_site.name is NOT unique
  • person.name is NOT unique
  • sales_opportunity.title is NOT unique

3. Multiple Statements - FORBIDDEN

-- FORBIDDEN - WILL FAIL
INSERT INTO company_site (name) VALUES ('A'); INSERT INTO company_site (name) VALUES ('B');

Why: Execute one statement per tool call.

4. Transaction Commands - FORBIDDEN

-- FORBIDDEN
BEGIN; INSERT INTO...; COMMIT;

CORRECT SQL Patterns (USE THESE)

Pattern 1: Simple INSERT (No RETURNING)

-- CORRECT - Simple INSERT
INSERT INTO company_site (name, address_city, created_at, updated_at)
VALUES ('Neue Firma GmbH', 'Berlin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

To get the ID after insert:

-- CORRECT - Query for the ID in a SEPARATE read_query call
SELECT id FROM company_site WHERE name = 'Neue Firma GmbH' ORDER BY created_at DESC LIMIT 1;

Pattern 2: Check-Then-Insert (Instead of UPSERT)

Step 1: Check if exists (read_query)

SELECT id, name FROM company_site WHERE name ILIKE '%Acme%' LIMIT 1;

Step 2a: If found - UPDATE (write_query)

UPDATE company_site SET updated_at = CURRENT_TIMESTAMP, notes = 'Updated info' WHERE id = 5;

Step 2b: If not found - INSERT (write_query)

INSERT INTO company_site (name, address_city, created_at, updated_at)
VALUES ('Acme GmbH', 'Munich', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

Pattern 3: Simple UPDATE

-- CORRECT
UPDATE person SET job_title = 'CEO', updated_at = CURRENT_TIMESTAMP WHERE id = 42;

Pattern 4: Simple DELETE

-- CORRECT
DELETE FROM event WHERE id = 123;

Pattern 5: Get ID After Insert

Two-step process:

-- Step 1: INSERT (write_query)
INSERT INTO person (name, email, company_site_id, created_at, updated_at)
VALUES ('Max Mustermann', '[email protected]', 5, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

-- Step 2: GET ID (read_query) - execute AFTER insert succeeds
SELECT id FROM person WHERE email = '[email protected]' ORDER BY created_at DESC LIMIT 1;

Tool Selection Guide

OperationToolNotes
SELECTread_queryAll SELECT statements
INSERTwrite_queryNo RETURNING, no ON CONFLICT
UPDATEwrite_queryNo RETURNING
DELETEwrite_queryNo RETURNING
Get ID after INSERTread_querySeparate call after INSERT

Common Mistakes and Fixes

Mistake 1: Using RETURNING to get ID

-- WRONG
INSERT INTO person (name) VALUES ('John') RETURNING id;

Fix:

-- Step 1: write_query
INSERT INTO person (name, created_at, updated_at) VALUES ('John', now(), now());

-- Step 2: read_query
SELECT id FROM person WHERE name = 'John' ORDER BY created_at DESC LIMIT 1;

Mistake 2: Using ON CONFLICT for upsert

-- WRONG
INSERT INTO company_site (name) VALUES ('Test')
ON CONFLICT (name) DO UPDATE SET updated_at = now();

Fix:

-- Step 1: read_query - Check existence
SELECT id FROM company_site WHERE name ILIKE '%Test%' LIMIT 1;

-- Step 2: write_query - INSERT if not found, UPDATE if found
-- If not found:
INSERT INTO company_site (name, created_at, updated_at) VALUES ('Test', now(), now());
-- If found (id=5):
UPDATE company_site SET updated_at = now() WHERE id = 5;

Mistake 3: Using now() vs CURRENT_TIMESTAMP

-- BOTH WORK - now() and CURRENT_TIMESTAMP are equivalent in PostgreSQL
INSERT INTO event (type, description, event_date, created_at)
VALUES ('call', 'Called customer', now(), CURRENT_TIMESTAMP);

Summary Checklist

Before executing SQL with write_query:

  • No RETURNING clause
  • No ON CONFLICT clause
  • Single statement only
  • No transaction commands (BEGIN/​COMMIT)
  • If you need the inserted ID: plan a follow-up read_query

Reference for Other Skills

This skill should be referenced by:

  • bel-crm-db - Main CRM database skill
  • bel-crm-schema-write-db - Schema and SQL examples
  • bel-insert-file-to-crm-and-link-it - File insertion
  • bel-download-file-from-crm-db - File retrieval
  • Any other skill that writes to the PostgreSQL CRM database

More Sales & marketing skills

revops logo
Sales & marketing

revops

Design and optimize systems connecting marketing, sales, and customer success into a unified revenue engine.

53.3K 104.9K
View
lead-magnets logo
Sales & marketing

lead-magnets

Strategic planning and optimization for email capture offers and gated content.

53.3K 103.4K
View
directory-submissions logo
Sales & marketing

directory-submissions

Directory submissions: the foundation layer of distribution that passes backlinks and discovery surface area into your marketing pages.

53.3K 76.3K
View
gsap-timeline logo
Sales & marketing

gsap-timeline

Sequence and choreograph multi-step animations with precise timing control and nested timelines.

15.9K 58.4K
View
launch-strategy logo
Sales & marketing

launch-strategy

Structured framework for planning product launches, feature announcements, and go-to-market strategies.

53.3K 56.8K
View
gws-drive-upload logo
Sales & marketing

gws-drive-upload

Upload files to Google Drive with automatic MIME type detection and metadata.

31.2K 47.2K
View
ci-cd-and-automation logo
Sales & marketing

ci-cd-and-automation

Automates CI/CD pipeline setup. Use when setting up or modifying build and deployment pipelines. Use when you need to automate quality gates, configure test runners in CI, or establish deployment strategies.

101.4K 43.2K
View
persona-team-lead logo
Sales & marketing

persona-team-lead

Team leadership persona with standup coordination, meeting prep, task delegation, and team communication.

31.2K 29.3K
View
recipe-find-large-files logo
Sales & marketing

recipe-find-large-files

Identify large Google Drive files consuming storage quota.

31.2K 29.2K
View

Sales & marketing AI tools

KreadoAI logo
Sales & marketing

KreadoAI

Revolutionize Video Creation with AI-Generated Avatars and Voices

Paid
View
Followr logo
Sales & marketing

Followr

Social media on autopilot

Paid
View
Logodiffusion logo
Sales & marketing

Logodiffusion

Design custom logos instantly with AI.

Paid
View
I
Sales & marketing

Ideogram

Text-heavy marketing and design images

Freemium
View
Prompt Silo logo
Sales & marketing

Prompt Silo

Boost Your SEO with Content and SEO Silos

Free
View
Marketing Blocks logo
Sales & marketing

Marketing Blocks

Revolutionize Your Marketing with AI-Powered MarketingBlocks!

Paid
View
Scrip AI logo
Sales & marketing

Scrip AI

10X faster & free AI content creation for 100+ use cases

Free
View
T
Sales & marketing

Tribescaler

Tribescaler | Make Your Tweets Go Viral

Paid
View