如何在 node-mysql2 准备好的语句中使用命名参数?

How to use named parameters in node-mysql2 prepared statements?

关于命名参数的 prepared statements document for mysql2 shows positional parameters. While there is some discussion,据我所知,它们没有记录在案。如果支持,如何使用命名参数?

例如,如何将以下内容转换为使用命名参数?

const config = require('config'); // for DB connection info
const mysql = require('mysql2/promise');
const connection = await mysql.createConnection({
    ...config.get('db.conn'),
    // (or however connection information is retrieved locally)
})

let sql = "SELECT ? AS a, ? AS b, ? + ? AS ab",
    values = [2, 3, 2, 3];
// note values[2:3] must equal values[0:1], otherwise results will be incorrect

let [result, columns] = await connection.execute(sql, values);

(请注意,数据库连接信息未包含在示例中,并通过使用配置包表示。在本地 运行 之前,示例必须通过以任何方式提供连接信息来完成首选。)

mysql2 在创建连接或池时或在查询时通过 named-placeholders package. The feature is disabled by default, and so must be enabled with the namedPlaceholders 选项对命名参数(有时在 mysql2 中称为“命名占位符”)提供一些支持被执行。

命名占位符使用与 PHP 中类似的语法:冒号后跟名称。与 PHP 不同,名称既可以是数字也可以是标识符。同样与 PHP 不同的是,值对象中使用的名称不能以冒号开头,否则将找不到该值。

queryexecute 方法支持命名占位符,Connection.format 如果 namedPlaceholders 为真连接。 preparemysql.formatPool.format.

不支持它们

Connection.format 还支持标识符的命名占位符;名称前面必须有两个冒号,而不是一个。与位置参数不同,如果正在处理位置参数,则所有参数都必须传递给 Connection.format;任何未指定的参数,无论是命名的还是位置的,都会变成 NULL(对于值)或 `undefined`(对于标识符)。

const config = require('config'); // for DB connection info
const mysql = require('mysql2/promise');

let sql = "SELECT :one AS a, :2 AS b, :one + :2 AS ab",
    values = {one: 2, 2: 3};
/* following won't work; colon prefix prevents values from being determined: */
//values = {":one": 2, ":2": 3};

/*****
 * Enable named placeholders for all queries through `pool`. 
 */
const pool = await mysql.createPool({
    namedPlaceholders: true,
    ...config.get('db.conn')
});
let [result, columns] = await pool.execute(sql, values);

/* Not supported; named placeholders remain unchanged */
pool.format(sql, values);
// result: "SELECT :one AS a, :2 AS b, :one + :2 AS ab"

/*****
 * Enable named placeholders only for some queries through `connection`.
 * Note also lack of `await` to continue before connection is completed.
 */
const connection = mysql.createConnection({
    //namedPlaceholders: false,
    ...config.get('db.conn')
});

/* also demonstrates lazy connection */ 
[result, columns] = await (await connection).execute({
    sql, values,
    namedPlaceholders: true,
});

/* Won't work because connection.config.namedPlaceholders is false */
(await connection).format(sql, values);
// result: SELECT :one AS a, :2 AS b, :one + :2 AS ab

/*****
 * Enable placeholders for all queries, which also enables them for 
 * `Connection.format` 
 */
const connection = await mysql.createConnection({
    namedPlaceholders: true,
    ...config.get('db.conn')
});

[result, columns] = await connection.execute(sql, values);

connection.format(sql, values);
// result: 'SELECT 2 AS a, 3 AS b, 2 + 3 AS ab'

/*****
 * Named and positional placeholders can be mixed, including "??" for identifiers. 
 * However, note how positional parameters are resolved.
 */
conn.format(
    "SELECT :one, :2, ? AS ::third FROM ??", 
    {one: 'a', 2: 'b', third:'3rd', 3:'c', 0:'zed', 1:'i'}
);
// result: "SELECT 'a', 'b', 'zed' AS `3rd` FROM `i`"

/* Missing parameters become NULL or `undefined` */
conn.format(
    "SELECT :one, :2 AS ::second, ? AS ::third FROM ??", 
    {one: 'a', 2: 'b', 3:'c', third: '3rd'}
);
// result: "SELECT 'a', 'b' AS `undefined`, NULL AS `3rd` FROM `undefined`"

/* If only positional parameters are passed, then not all values need to be given. 
 * Named placeholders and positional placeholders past the end of the array remain 
 * as-is in the statement.
 */
conn.format(
    "SELECT :one, :2, ? AS ::third FROM ??", 
    ['zed']
);
// result: "SELECT :one, :2, 'zed' AS ::third FROM ??"

/* The values for named placeholders must be an object, not an array. */
conn.format("SELECT :0 AS a, :1 AS b, :0+:1 AS ab", [2,3]);
// result: "SELECT :0 AS a, :1 AS b, :0+:1 AS ab"
conn.format("SELECT :0 AS a, :1 AS b, :0+:1 AS ab", {0:2, 1:3});
// result: "SELECT 2 AS a, 3 AS b, 2+3 AS ab"