{"id":24312509,"url":"https://github.com/sharaal/sql-mysql","last_synced_at":"2026-04-29T12:38:29.401Z","repository":{"id":57368261,"uuid":"174520714","full_name":"Sharaal/sql-mysql","owner":"Sharaal","description":"Complex queries can be written with normal SQL, including the values needs to be bound and prefixed with the `sql` tag.","archived":false,"fork":false,"pushed_at":"2019-05-13T15:19:25.000Z","size":33,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-29T10:13:35.855Z","etag":null,"topics":["mysql","nodejs","query-builder","sql","tagged-template-literals"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Sharaal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-08T10:53:22.000Z","updated_at":"2019-05-13T15:19:27.000Z","dependencies_parsed_at":"2022-09-05T19:21:28.997Z","dependency_job_id":null,"html_url":"https://github.com/Sharaal/sql-mysql","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/Sharaal/sql-mysql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sharaal%2Fsql-mysql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sharaal%2Fsql-mysql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sharaal%2Fsql-mysql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sharaal%2Fsql-mysql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Sharaal","download_url":"https://codeload.github.com/Sharaal/sql-mysql/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sharaal%2Fsql-mysql/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32426588,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T12:24:25.982Z","status":"ssl_error","status_checked_at":"2026-04-29T12:24:24.439Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mysql","nodejs","query-builder","sql","tagged-template-literals"],"created_at":"2025-01-17T08:17:58.205Z","updated_at":"2026-04-29T12:38:29.386Z","avatar_url":"https://github.com/Sharaal.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Complex queries can be written with normal SQL, including the values needs to be bound and prefixed with the `sql` tag.\n\nThe package is highly inspired by [slonik](https://www.npmjs.com/package/slonik) and the article having a critical look at [knex](https://www.npmjs.com/package/knex):\n\nhttps://medium.com/@gajus/stop-using-knex-js-and-earn-30-bf410349856c\n\nSpecial thanks to [gajus](https://github.com/gajus).\n\nAlso it's more a research than a production ready package to understand the concepts behind in deep and get more experience in working effectively with SQL.\n\n# Initialization\n\n```javascript\nconst sql = require('sql-mysql')\n```\n\n# Syntax Highlighting\n\n## Atom\n\n1. Install `language-babel` package\n2. In the settings of this package search for \"JavaScript Tagged Template Literals Grammar Extensions\" and add the support for SQL via `sql:source.sql`\n3. If it doesn't work disable \"Use Tree Sitter Parsers\" in the core settings\n\n# Alternative databases\n\n* PostgreSQL: [sql-pg](https://www.npmjs.com/package/sql-pg)\n\n# Examples\n\n## Extract and bind values\n\n```javascript\nconst email = 'email'\nconst passwordhash = 'passwordhash'\n\nconst result = await connection.query(sql`\n  SELECT * FROM users WHERE email = ${email} AND passwordhash = ${passwordhash}\n`)\n\n// sql: SELECT * FROM users WHERE email = ? AND passwordhash = ?\n// values: ['email', 'passwordhash']\n```\n\n## Escape keys for tables and columns\n\n```javascript\nconst table = 'users'\nconst columns = ['id', 'email']\n\nconst result = await connection.query(sql`\n  SELECT ${sql.keys(columns)} FROM ${sql.key(table)}\n`)\n\n// sql: SELECT `id`, `email` FROM `users`\n// values: []\n```\n\nIf the parameter is an object (e.g. a user) the keys of the object will be used:\n\n```javascript\nconst user = { id: 'id', email: 'email' }\n\nconst result = await connection.query(sql`\n  SELECT ${sql.keys(user)} FROM users\n`)\n\n// sql: SELECT `id`, `email` FROM `users`\n// values: []\n```\n\n## Support list of values\n\n```javascript\n\nconst values = ['email', 'passwordhash']\n\nconst result = await connection.query(sql`\n  INSERT INTO users (email, passwordhash) VALUES (${sql.values(values)})\n`)\n\n// sql: INSERT INTO users (email, passwordhash) VALUES (?, ?)\n// values: ['email', 'passwordhash']\n```\n\nIf the parameter is an object (e.g. a user) the values of the object will be used:\n\n```javascript\nconst user = { email: 'email', passwordhash: 'passwordhash' }\n\nconst result = await connection.query(sql`\n  INSERT INTO users (email, passwordhash) VALUES (${sql.values(user)})\n`)\n\n// sql: INSERT INTO users (email, passwordhash) VALUES (?, ?)\n// values: ['email', 'passwordhash']\n```\n\n## Support multiple list of values\n\n```javascript\nconst valuesList = [\n  ['emailA', 'passwordhashA'],\n  ['emailB', 'passwordhashB']\n]\n\nconst result = await connection.query(sql`\n  INSERT INTO users (email, passwordhash) VALUES ${sql.values(valuesList)}\n`)\n\n// sql: INSERT INTO users (email, passwordhash) VALUES (?, ?), (?, ?)\n// values: ['emailA', 'passwordhashA', 'emailB', 'passwordhashB']\n```\n\nIf the parameter is an array of objects (e.g. list of users) the values of the objects will be used:\n\n```javascript\nconst users = [\n  { email: 'emailA', passwordhash: 'passwordhashA' },\n  { email: 'emailB', passwordhash: 'passwordhashB' }\n]\n\nconst result = await connection.query(sql`\n  INSERT INTO users (email, passwordhash) VALUES ${sql.values(users)}\n`)\n\n// sql: INSERT INTO users (email, passwordhash) VALUES (?, ?), (?, ?)\n// values: ['emailA', 'passwordhashA', 'emailB', 'passwordhashB']\n```\n\n## Support assignments for updates\n\n```javascript\nconst user = { email: 'email', passwordhash: 'passwordhash' }\n\nconst result = await connection.query(sql`\n  UPDATE users SET ${sql.assignments(user)} WHERE id = 'id'\n`)\n\n// sql: UPDATE users SET `email` = ?, `passwordhash` = ? WHERE id = 'id'\n// values: ['email', 'passwordhash']\n```\n\n## Support pairs of column keys and values using as alternative of assignments for updates\n\n```javascript\nconst user = { email: 'email', passwordhash: 'passwordhash' }\n\nconst result = await connection.query(sql`\n  UPDATE users SET ${sql.pairs(user, ', ')} WHERE id = 'id'\n`)\n\n// sql: UPDATE users SET `email` = ?, `passwordhash` = ? WHERE id = 'id'\n// values: ['email', 'passwordhash']\n```\n\n## Support conditions for basic use cases\n\n```javascript\nconst user = { email: 'email', passwordhash: 'passwordhash' }\n\nconst result = await connection.query(sql`\n  SELECT * FROM users WHERE ${sql.conditions(user)}\n`)\n\n// sql: SELECT * FROM users WHERE `email` = ? AND `passwordhash` = ?\n// values: ['email', 'passwordhash']\n```\n\n## Support pairs of column keys and values using as alternative of conditions\n\n```javascript\nconst user = { email: 'email', passwordhash: 'passwordhash' }\n\nconst result = await connection.query(sql`\n  SELECT * FROM users WHERE ${sql.pairs(user, ' AND ')}\n`)\n\n// sql: SELECT * FROM users WHERE `email` = ? AND `passwordhash` = ?\n// values: ['email', 'passwordhash']\n```\n\n## Support for nested queries\n\n```javascript\nconst state = 'active'\nconst email = 'email'\nconst passwordhash = 'passwordhash'\n\nconst result = await connection.query(sql`\n  SELECT * FROM users WHERE\n    state = ${state}\n    AND\n    id = (${sql`SELECT id FROM users WHERE email = ${email} AND passwordhash = ${passwordhash}`})\n`)\n\n// sql: SELECT * FROM users WHERE\n//         state = ?\n//         AND\n//         id = (SELECT id FROM users WHERE email = ? AND passwordhash = ?)\n// values: ['active', 'email', 'passwordhash']\n```\n\n## Support for limit, offset and pagination\n\n```javascript\nconst actualLimit = 10\nconst maxLimit = 50\nconst offset = 20\n\nconst result = await connection.query(sql`\n  SELECT * FROM users ${sql.limit(actualLimit, maxLimit)} ${sql.offset(offset)}\n`)\n\n// sql: SELECT * FROM users LIMIT 10 OFFSET 20\n// values: []\n```\n\n`maxLimit` is optional, but it should be set with a non user defined number to ensure a user can't select an infinite number of rows.\n\nBecause of pagination is a common use case there is also a pagination shorthand:\n\n```javascript\nconst page = 5\nconst pageSize = 10\n\nconst result = await connection.query(sql`\n  SELECT * FROM users ${sql.pagination(page, pageSize)}\n`)\n\n// sql: SELECT * FROM users LIMIT 10 OFFSET 50\n// values: []\n```\n\n# Extend with own fragment methods\n\nIt's possible to define own fragment methods by adding them to the `sql` tag:\n\n```javascript\nconst bcrypt = require('bcrypt')\n\nsql.passwordhash = (password, saltRounds = 10) =\u003e ({\n  sql: '?',\n  values: [bcrypt.hashSync(password, saltRounds)]\n})\n\nconst user = { email: 'email' }\nconst password = 'password'\n\nconst result = await connection.query(sql`\n  INSERT INTO users (email, passwordhash) VALUES (${sql.values(user)}, ${sql.passwordhash(password)})\n`)\n\n// sql: INSERT INTO users (email, passwordhash) VALUES (?, ?)\n// values: ['email', '$2b$10$ODInlkbnvW90q.EGZ.1Ale3YpOqqdn0QtAotg8q/JzM5HGky6Q2j6']\n```\n\nIt's also possible to reuse existing fragments methods to define own ones:\n\n```javascript\nconst bcrypt = require('bcrypt')\n\nsql.passwordhash = (password, saltRounds = 10) =\u003e sql.values([bcrypt.hashSync(password, saltRounds)])\n\nconst user = { email: 'email' }\nconst password = 'password'\n\nconst result = await connection.query(sql`\n  INSERT INTO users (email, passwordhash) VALUES (${sql.values(user)}, ${sql.passwordhash(password)})\n`)\n\n// sql: INSERT INTO users (email, passwordhash) VALUES (?, ?)\n// values: ['email', '$2b$10$ODInlkbnvW90q.EGZ.1Ale3YpOqqdn0QtAotg8q/JzM5HGky6Q2j6']\n```\n\nOr by define a constant result object if no values needed:\n\n```javascript\nsql.first = {\n  sql: `LIMIT 1`,\n  values: []\n}\n\nconst result = await connection.query(sql`\n  SELECT * FROM users ${sql.first}\n`)\n\n// sql: SELECT * FROM users LIMIT 1\n// values: []\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsharaal%2Fsql-mysql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsharaal%2Fsql-mysql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsharaal%2Fsql-mysql/lists"}