What about JDBC?
Here's a few examples stolen from the doc page for the next.jdbc library (https://github.com/seancorfield/next-jdbc):
> clj
Clojure 1.10.1
user=> (require '[next.jdbc :as jdbc])
nil
user=> (def db {:dbtype "h2" :dbname "example"})
#'user/db
user=> (def ds (jdbc/get-datasource db))
#'user/ds
user=> (jdbc/execute! ds ["
create table address (
id int auto_increment primary key,
name varchar(32),
email varchar(255)
)"])
[#:next.jdbc{:update-count 0}]
user=> (jdbc/execute! ds ["
insert into address(name,email)
values('John Smith','john.smith@email.org')"])
[#:next.jdbc{:update-count 1}]
user=> (jdbc/execute! ds ["select * from address"])
[#:ADDRESS{:ID 1, :NAME "John Smith", :EMAIL "john.smith@email.org"}]
That is an example REPL session to setup the library, setup a datasource, create a table, insert a row into the table, and then select from the table. The "user=>" part is the REPL command prompt. Essentially it's one statement for each SQL query executed, and 1 or 2 statements to setup the JDBC datasource. This is tight.
You can see the return from the select contains clojure native data-structures. It returns a list of rows, where each row is a map of fieldName to fieldValue. You can now go to town and manipulate lists and maps to your hearts content, convert the payload to HTML or JSON or whatever you like.