Search

Search IconIcon to open search

Run DuckDB in your Website

Last updated by Simon Späti

With a simple HTML script (there is also React.js and Vue example) - you can embedd a DuckDB with WASM query with like this:


CREATE TABLE notes (
  id INTEGER,
  title VARCHAR(100),
  created_date DATE,
  tags VARCHAR(200),
  word_count INTEGER
);

CREATE TABLE links (
  from_note_id INTEGER,
  to_note_id INTEGER,
  link_type VARCHAR(20)
);

INSERT INTO notes VALUES
  (1, 'Python Basics', '2024-01-15', 'programming,python', 450),
  (2, 'Machine Learning Intro', '2024-02-01', 'ai,python,data-science', 820),
  (3, 'Data Visualization', '2024-02-10', 'python,data-science,charts', 650),
  (4, 'Web Scraping Guide', '2024-03-05', 'python,automation', 580);

INSERT INTO links VALUES
  (2, 1, 'builds-on'),
  (3, 1, 'uses'),
  (3, 2, 'related'),
  (4, 1, 'uses');

-- Find most connected notes (your "hub" notes)
SELECT 
  n.title,
  COUNT(DISTINCT l.to_note_id) as outgoing_links,
  n.tags,
  n.word_count
FROM notes n
LEFT JOIN links l ON n.id = l.from_note_id
GROUP BY n.id, n.title, n.tags, n.word_count
ORDER BY outgoing_links DESC;

Just add:

1
2
3
4
5
6
<pre class="sql-workbench-embedded">
<code>
SELECT 'your SQL stmt here'
</code>
</pre>
<script src="https://unpkg.com/sql-workbench-embedded@0.1.2"></script>

The source is on GitHub, check out sql-workbench-embedded, a lightweight JavaScript library that transforms static SQL code blocks into interactive, browser-based SQL execution environments using DuckDB WASM.

The website SQL Workbench Embedded showcases more features and documentation.

# Path Resolution to DB

The library automatically resolves relative file paths in SQL queries:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
-- Relative path
SELECT * FROM 'data.parquet';
-- Resolves to: https://data.sql-workbench.com/data.parquet

-- Absolute path
SELECT * FROM '/data.parquet';
-- Resolves to: https://your-domain.com/data.parquet

-- Already absolute URL (unchanged)
SELECT * FROM 'https://example.com/data.parquet';

# Accessing DuckDB in my Apache Server

I created ad DuckDB database on http://ssp.sh/brain/de/weather-noaa.duckdb. Let’s check if we can access it:

First Time Setup

Wait a couple of seconds before you run below example as the database attachment happens in the background.

-- Query the attached noaa weather data
-- DB has been attached as `noaa`, and table `weather`
SUMMARIZE FROM noaa.weather;

The ATTACH statement lets you connect to external DuckDB database files
hosted remotely. This is perfect for sharing pre-computed datasets without loading them
into the main database.

This is how I created the database (LIMIT 10'000)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
CREATE TABLE weather AS SELECT
    now() AS __load_time,
    -- Transform raw CSV columns to proper NOAA weather schema
    COALESCE(column0, 'UNKNOWN') AS station_id,
    COALESCE(STRPTIME(CAST(column1 AS VARCHAR), '%Y%m%d'), DATE '1900-01-01') AS measurement_date,
    COALESCE(column2, 'UNKNOWN') AS measurement_type, -- TMIN, TMAX, PRCP, SNOW, etc.
    CAST(column3 AS FLOAT) / 10.0 AS measurement_value, -- Convert from tenths
    column4 AS measurement_flag,
    column5 AS quality_flag,
    column6 AS source_flag,
    column7 AS observation_time,
    -- Add derived fields for analytics
    YEAR(STRPTIME(CAST(column1 AS VARCHAR), '%Y%m%d')) AS measurement_year,
    MONTH(STRPTIME(CAST(column1 AS VARCHAR), '%Y%m%d')) AS measurement_month,
    DAYOFYEAR(STRPTIME(CAST(column1 AS VARCHAR), '%Y%m%d')) AS measurement_day_of_year,
    -- Temperature conversions for common analysis
    CASE
        WHEN column2 = 'TMIN' THEN CAST(column3 AS FLOAT) / 10.0
        ELSE NULL
    END AS temp_min_celsius,
    CASE
        WHEN column2 = 'TMAX' THEN CAST(column3 AS FLOAT) / 10.0
        ELSE NULL
    END AS temp_max_celsius,
    CASE
        WHEN column2 = 'PRCP' THEN CAST(column3 AS FLOAT) / 10.0
        ELSE NULL
    END AS precipitation_mm
FROM read_csv('https://noaa-ghcn-pds.s3.amazonaws.com/csv.gz/by_year/2025.csv.gz')
LIMIT 10000;

Origin: DuckDB
References:
Created 2025-11-02