Je hebt een tabel op een webpagina. Je hebt het nodig in je database.
De handmatige aanpak: kopiëren naar Excel, opschonen, CSV exporteren, handmatig CREATE TABLE schrijven, LOAD DATA of COPY gebruiken, fouten debuggen.
De betere aanpak: genereer direct complete SQL—CREATE TABLE met afgeleide types, INSERT-statements met juiste escaping.
Zo bouw je een webtabel-naar-SQL-converter.
Het Outputformaat
Een complete SQL-export moet bevatten:
-- Geëxporteerd met HTML Table Exporter PRO
CREATE TABLE producten (
product_id INTEGER,
naam TEXT,
prijs REAL,
op_voorraad TEXT
);
INSERT INTO producten (product_id, naam, prijs, op_voorraad) VALUES
(1, 'Widget', 29.99, 'true'),
(2, 'Gadget', 49.99, 'false'),
(3, 'O''Brien''s Special', 19.99, 'true');
Kernvereisten:
- Geldige tabelnaam (SQL-veilige identifier)
- Geldige kolomnamen (geen spaties, geen speciale tekens)
- Passende kolomtypen (INTEGER, REAL, TEXT)
- Correct ge-escapete waarden (enkele aanhalingstekens verdubbeld)
- NULL-afhandeling
Stap 1: Identifiers Opschonen
SQL-identifiers (tabel- en kolomnamen) hebben strikte regels:
- Geen spaties of speciale tekens
- Mag niet met een cijfer beginnen
- Moet in kleine letters voor portabiliteit
function sanitizeSqlIdentifier(name, fallback) {
let id = (name || "").toString().trim();
if (!id) id = fallback || "col";
id = id
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "") // Verwijder accenten (café → cafe)
.toLowerCase()
.replace(/[^a-z0-9_]+/g, "_") // Vervang ongeldige tekens met underscore
.replace(/^_+|_+$/g, ""); // Trim begin/eind-underscores
// SQL-identifiers mogen niet met een cijfer beginnen
if (/^[0-9]/.test(id)) {
id = "_" + id;
}
if (!id) id = fallback || "col";
return id;
}
Voorbeelden:
- "Product Naam" → "product_naam"
- "Prijs (€)" → "prijs"
- "2024 Omzet" → "_2024_omzet"
- "Préço" → "preco"
Stap 2: Unieke Kolomnamen Genereren
Tabellen kunnen dubbele headers hebben. SQL kan geen dubbele kolomnamen hebben.
function generateColumnNames(headerRow) {
const usedNames = new Set();
return headerRow.map((header, index) => {
const base = sanitizeSqlIdentifier(header, `col_${index + 1}`);
let candidate = base;
let counter = 1;
while (usedNames.has(candidate)) {
candidate = `${base}_${counter}`;
counter++;
}
usedNames.add(candidate);
return candidate;
});
}
Voorbeelden:
- ["Naam", "Naam", "Waarde"] → ["naam", "naam_1", "waarde"]
- ["", "", "Data"] → ["col_1", "col_2", "data"]
Stap 3: Kolomtypen Afleiden
SQL heeft drie hoofdtypen die we nodig hebben:
- INTEGER: Gehele getallen
- REAL: Decimale getallen
- TEXT: Al het andere
De afleiding bemonstert waarden uit de kolom en kiest het meest specifieke type dat bij alle waarden past:
function inferSqlColumnTypes(rows, headerRowIndex = 0) {
const headerRow = rows[headerRowIndex] || [];
const dataRows = rows.slice(headerRowIndex + 1);
const colCount = headerRow.length;
const types = new Array(colCount).fill("TEXT");
for (let col = 0; col < colCount; col++) {
// Bemonstert maximaal 50 niet-lege waarden
const values = [];
for (let r = 0; r < dataRows.length && values.length < 50; r++) {
const cell = dataRows[r][col];
const v = cell != null ? String(cell).trim() : "";
if (v !== "") values.push(v);
}
if (values.length === 0) {
types[col] = "TEXT";
continue;
}
// Controleer of alle waarden integers zijn
let allInt = true;
let allNumeric = true;
for (const v of values) {
if (!/^[-+]?\d+$/.test(v)) {
allInt = false;
}
if (!/^[-+]?\d+([.,]\d+)?$/.test(v)) {
allNumeric = false;
}
}
if (allInt) {
types[col] = "INTEGER";
} else if (allNumeric) {
types[col] = "REAL";
} else {
types[col] = "TEXT";
}
}
return types;
}
Kernbeslissingen:
- Bemonstert slechts 50 waarden voor prestaties bij grote tabellen
- INTEGER is strikter dan REAL (geen decimalen toegestaan)
- Als EEN waarde niet past, val terug op TEXT
- Lege kolommen worden standaard TEXT
Stap 4: Waarden Escapen
SQL-strings vereisen escaping van enkele aanhalingstekens door ze te verdubbelen:
function sqlEscapeValue(raw, type) {
// NULL-afhandeling
if (raw == null) return "NULL";
const v = String(raw).trim();
if (v === "") return "NULL";
// Voor numerieke typen, probeer een niet-geciteerd getal te retourneren
if (type === "INTEGER" || type === "REAL") {
const normalized = v.replace(",", "."); // Verwerk EU decimaalformaat
const num = Number(normalized);
if (!Number.isNaN(num) && Number.isFinite(num)) {
return normalized;
}
// Val door naar TEXT-afhandeling als het geen geldig getal is
}
// TEXT of fallback: escape enkele aanhalingstekens
const escaped = v.replace(/'/g, "''");
return `'${escaped}'`;
}
Voorbeelden:
-
"Hallo"→'Hallo' -
"O'Brien"→'O''Brien' -
"Het is \"geciteerd\""→'Het is "geciteerd"' -
123(INTEGER) →123 -
45.67(REAL) →45.67 -
""→NULL -
null→NULL
Stap 5: De Volledige SQL Genereren
function tableToSqlString(tableInfo) {
const rows = tableInfo.rows || [];
if (!rows.length) return "";
const headerRowIndex = tableInfo.headerRowIndex || 0;
const headerRow = rows[headerRowIndex];
const dataRows = rows.slice(headerRowIndex + 1);
if (!headerRow) return "";
// Genereer veilige kolomnamen
const columnNames = generateColumnNames(headerRow);
// Leid kolomtypen af
const types = inferSqlColumnTypes(rows, headerRowIndex);
// Genereer veilige tabelnaam
const rawTableName = tableInfo.slug || tableInfo.name || "tabel";
let tableName = sanitizeSqlIdentifier(rawTableName, "tabel");
if (!tableName) tableName = "tabel_export";
// BOUW CREATE TABLE
const createLines = columnNames.map((col, i) =>
` ${col} ${types[i] || "TEXT"}`
);
const createStmt = `CREATE TABLE ${tableName} (\n${createLines.join(",\n")}\n);`;
// BOUW INSERT-STATEMENTS
const insertHeader = `INSERT INTO ${tableName} (${columnNames.join(", ")}) VALUES`;
const valueLines = dataRows.map(row => {
const values = columnNames.map((_, i) => {
const cell = row[i];
const type = types[i] || "TEXT";
return sqlEscapeValue(cell, type);
});
return ` (${values.join(", ")})`;
});
// COMBINEER
let sql = `-- Geëxporteerd met HTML Table Exporter PRO\n\n${createStmt}\n\n`;
if (valueLines.length) {
sql += `${insertHeader}\n${valueLines.join(",\n")};\n`;
}
return sql;
}
Voorbeeldoutput
Invoertabel:
| Product | Prijs | Aant |
|---|---|---|
| Widget | 29.99 | 100 |
| O'Brien's | 19.99 | 50 |
Output:
-- Geëxporteerd met HTML Table Exporter PRO
CREATE TABLE producten (
product TEXT,
prijs REAL,
aant INTEGER
);
INSERT INTO producten (product, prijs, aant) VALUES
('Widget', 29.99, 100),
('O''Brien''s', 19.99, 50);
Randgevallen Afhandelen
Lege Tabellen
if (!rows.length) return "";
if (!headerRow) return "";
Retourneer een lege string in plaats van ongeldige SQL.
Kolommen met Alleen NULL
Kolommen met alleen lege/null-waarden krijgen het TEXT-type. De afleidingsfunctie verwerkt dit:
if (values.length === 0) {
types[col] = "TEXT";
continue;
}
Gemengde Getalformaten
De escaper normaliseert komma-decimalen:
const normalized = v.replace(",", ".");
"1,234.56" blijft zoals het is. "1.234,56" (EU-formaat) moet genormaliseerd worden vóór het de SQL-generator bereikt—dat is de taak van de opschoningspresets.
Zeer Lange Waarden
TEXT-kolommen in SQLite/PostgreSQL verwerken willekeurige lengte. Geen afkapping nodig. Voor MySQL's VARCHAR-limieten moet je de lengte specificeren of expliciet TEXT gebruiken.
Database-compatibiliteit
De gegenereerde SQL is opzettelijk eenvoudig:
| Feature | SQLite | PostgreSQL | MySQL |
|---|---|---|---|
| CREATE TABLE | ✅ | ✅ | ✅ |
| INTEGER/REAL/TEXT | ✅ | ✅ | ✅ |
| Multi-rij INSERT | ✅ | ✅ | ✅ |
| Enkele quote escape | ✅ | ✅ | ✅ |
Voor databasespecifieke features (constraints, indexen, schema's) breid je de generator uit. Voor eenvoudige data-import werkt dit overal.
De Export Gebruiken
# SQLite
sqlite3 mijndb.db < export.sql
# PostgreSQL
psql -d mijndb -f export.sql
# MySQL
mysql mijndb < export.sql
Of plak direct in je databaseclient.
Lees voor meer over het exporteren van tabellen naar andere formaten onze gids over de beste Chrome-extensies voor het exporteren van tabellen.
Wil je SQL-exports zonder code te schrijven? Meer informatie op gauchogrid.com/nl/html-table-exporter of probeer het gratis in de Chrome Web Store.
Top comments (0)