SQL to HTML Table Converter

Put the rows on a page. Paste your INSERT statements and get semantic markup with a real header, escaped values and alignment that follows the data.

To convert SQL to an HTML table, paste your INSERT statements above. Each row becomes a tr, the column names become th cells inside a thead, and every value is escaped so an ampersand or an angle bracket in your data cannot break the page. Choose a bare fragment to paste into an existing template, or a standalone document with styling included.

Want to sort or filter before you publish? Open the app

The two reasons anyone needs this

The first is a status page or an internal dashboard that is just a table, and the table has to come from somewhere. Somebody has the rows as INSERT statements, the page needs markup, and standing up a template engine for six rows of reference data is not a good use of an afternoon.

The second is email. A newsletter tool, a support macro or an alerting template needs a table, and every one of them wants HTML rather than Markdown. This is the fastest path from rows to something you can paste into that box.

Both cases want the same thing: markup that is correct on the first attempt, with no half-open tag and no value that eats the rest of the row.

Worked example

A reference table, the sort that ends up on an internal page:

INSERT INTO regions (region_code, region_name, opened_on, headcount) VALUES
  ('01', 'North Coast', '2019-03-04', 42),
  ('02', 'Lakeside & Vale', '2020-07-19', 17);

And the fragment:

<table>
  <thead>
    <tr><th>region_code</th><th>region_name</th><th>opened_on</th><th class="num">headcount</th></tr>
  </thead>
  <tbody>
    <tr><td>01</td><td>North Coast</td><td>2019-03-04</td><td class="num">42</td></tr>
    <tr><td>02</td><td>Lakeside &amp; Vale</td><td>2020-07-19</td><td class="num">17</td></tr>
  </tbody>
</table>

The ampersand in the second region name came out as &amp;, which is what a browser renders as a single ampersand. Written raw it would be an incomplete entity, and some parsers will swallow the characters after it. The num class is on the headcount column only, because that is the only column whose every value is a number.

Escaping, including the one everybody forgets

Four characters are obvious: &, <, > and the double quote. The fifth is the apostrophe, and it is the one most converters skip because a bare apostrophe renders fine inside a cell.

It matters the moment the markup is reused somewhere else, which happens constantly: pasted inside a single-quoted attribute, dropped into a JavaScript string, run through a template that quotes with apostrophes. So ' becomes &#39; everywhere, and a customer called O'Hara cannot terminate anything.

A line break inside a value becomes <br> rather than a literal newline, so a two-line note renders as two lines instead of collapsing into one the way HTML whitespace rules would have it.

Fragment or full page

  • Table only gives you a bare <table> element with no wrapper, no doctype and no CSS. This is what you want when the page already exists and has its own styles.
  • Full HTML page wraps it in a document with a title, a character set declaration and a small stylesheet: collapsed borders, a shaded header row, tabular figures on the numeric columns. Save it and open it, or use it as a starting point.
  • Styling off strips the num class as well as the CSS, so the markup is as plain as it can be. Use it when a linter or a content management system objects to classes it does not recognise.
  • Caption adds a <caption> element, which is the accessible way to title a table and is read out by screen readers before the contents.

Why the markup looks old-fashioned

There is no <div> grid here and no utility classes. A table of data is one of the few things HTML has a genuinely correct element for, and a real <table> with a <thead> is what makes a screen reader announce the column name before each cell, what makes the browser's own find-in-page work sensibly, and what lets someone select the table and paste it into a spreadsheet with its structure intact.

It also means the output is stable. Semantic table markup has not changed in twenty years and will not change again, so a page generated today still works when the framework it was pasted into has been replaced twice.

Frequently Asked Questions

Does it produce a full page or just the table?

Either. The default is a bare table element ready to paste into an existing template. Switch to full page and you get a complete document with a doctype, a character set, a title and a small stylesheet, which you can save and open directly.

Are values escaped properly?

All five characters that matter, apostrophe included. Most converters skip the apostrophe because it renders fine in a cell, but it breaks the moment the markup is pasted inside a single-quoted attribute or a JavaScript string, which is a very common next step.

What happens to a line break inside a value?

It becomes a br tag. HTML collapses whitespace, so a raw newline in the source would render as a single space and your two-line note would silently become one line.

Why is only one of my columns right-aligned?

Because only one column is numeric. Alignment follows the type the column actually holds, decided from all of its values. A code column padded with a leading zero is text, and right-aligning it would present an identifier as a quantity.

Can I add a caption?

Yes, and it is worth doing. A caption element is the accessible way to title a table: a screen reader reads it before the contents, so someone hears what the table is before they hear the first cell. Type it in the options and it is added for you.

Will this work in an email template?

The markup is plain enough for most email clients, but email is its own world. Older Outlook builds ignore the stylesheet entirely, so if the table has to look right in an email you will usually want inline styles on top of what comes out here.

Put those rows on a page

Semantic markup, everything escaped, fragment or full document. Copy and paste.

Back to the converter