Mysql 如何在POST body的基础上创建动态insert语句

Mysql 如何在POST body的基础上创建动态insert语句,mysql,node.js,mysqljs,Mysql,Node.js,Mysqljs,body对象中的属性数不同,这取决于值user\u type 如果用户类型为求职者,则body对象具有以下属性-->用户名、用户类型、姓名、电子邮件、密码、简历、简历日期时间、薪资期望。我创建了硬编码的insert语句,如下--> 插入用户(用户名、用户类型、姓名、电子邮件、密码、简历、简历日期时间、薪资期望)值(?、、、、、、、、、?) 如果用户类型为雇主,则主体对象具有以下属性-->用户名、用户类型、名称、电子邮件、密码、公司名称、公司档案。本例的Insert语句为--> 在用户(用户名、用

body对象中的属性数不同,这取决于值
user\u type

如果
用户类型
求职者,则body对象具有以下属性-->用户名、用户类型、姓名、电子邮件、密码、简历、简历日期时间、薪资期望。我创建了硬编码的insert语句,如下-->

插入用户(用户名、用户类型、姓名、电子邮件、密码、简历、简历日期时间、薪资期望)值(?、、、、、、、、、?)

如果
用户类型
雇主,则主体对象具有以下属性-->用户名、用户类型、名称、电子邮件、密码、公司名称、公司档案。本例的Insert语句为-->

在用户(用户名、用户类型、姓名、电子邮件、密码、公司名称、公司简介)中插入值(?、、?、?、?、?、?)


那么,如何根据POST请求主体中不同数量的属性创建动态插入查询呢?

这不是一个好答案,但它可以解决这个小问题,但如果有人知道这一点,请发布一个答案

let keys = [];
let values = [];
let escapedsql = [];
Object.keys(req.body).forEach(key => {
    keys.push(key);
    values.push(req.body[key]);
    escapedsql.push('?')
})
let postBody = 'insert into users (' + keys.join() + ') values (' + escapedsql.join() + ')';
let sql = connection.format(postBody, values);

这不是一个好的答案,但它的工作,所以要围绕这个小黑客,但如果有人知道这一点,然后请张贴一个答案

let keys = [];
let values = [];
let escapedsql = [];
Object.keys(req.body).forEach(key => {
    keys.push(key);
    values.push(req.body[key]);
    escapedsql.push('?')
})
let postBody = 'insert into users (' + keys.join() + ') values (' + escapedsql.join() + ')';
let sql = connection.format(postBody, values);

这是由
mysqljs
模块为您处理的,因此您无需过度思考或过度设计它。将insert有效负载作为一个对象提供,其中键与表字段名共享相同的命名。无论您提供什么,都将在插入中使用。如果您不提供字段,它将遵循数据库架构中的表默认值(
id
将自动填充并递增,如果您以这种方式进行设置,
created\u at
timestamp
或其他类似日期字段,如果字段设置为在未提供值时使用默认值,则将使用该默认值)

有关更多详细信息,请参阅此处的文档:

下面是使用您提供的两个场景的示例

var mysql = require('mysql');
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'me',
  password: 'secret',
  database: 'my_db'
});

connection.connect();

let job_seeker = {
  username: 'j.smith',
  user_type: 'job_seeker',
  name: 'john smith',
  email: 'j.smith@example.com',
  password: 'keyboard_cat',
  resume: true,
  resume_date_time: '2109-01-01',
  salary_expectation: 100000
};

let employer = {
  username: 'b.burke',
  user_type: 'employer',
  name: 'betty burke',
  email: 'b.burke@example.com',
  password: 'admin_cat',
  company_name: 'Acme Inc.',
  company_profile: 'http://acme.example.com/about_us/'
};


connection.query('INSERT INTO users SET ?', job_seeker, function(error, results, fields) {
  if (error) throw error;
  console.log(results.insertId);
});

connection.query('INSERT INTO users SET ?', employer, function(error, results, fields) {
  if (error) throw error;
  console.log(results.insertId);
});

// if a scenario exists where you might encounter unique key conflicts, consider using a query model that will update on duplicates:

connection.query('INSERT INTO users SET ? ON DUPLICATE KEY UPDATE', employer, function(error, results, fields) {
  if (error) throw error;
  console.log(results.insertId);
});

// this would update every field provided in the employer object. If you didn't want to update every fields, you'd have to list out only the fields you'd like to update:

connection.query('INSERT INTO users SET ? ON DUPLICATE KEY UPDATE name = VALUES(name)', employer, function(error, results, fields) {
  if (error) throw error;
  console.log(results.insertId);
});

// in the above example, only the name field will be updated if a duplicate is found, even though the full employer object is provided.
如果在将
POST
正文传递到代码中的这一步之前正确地构造了它,那么您可以节省一些时间,只需将它传递到查询函数,而无需额外的工作或对象构造或操作

根据评论进行编辑

如果您的计划包括一些查询参数,您可能希望使用更新而不是插入。无论采用哪种方式,我们都可以将此作为一个示例,说明如何演示
mysqljs
模块提供的动态功能

每次使用
时,它都是一个占位符,映射到函数后面的数组索引

在“文档”部分“链接”中,您可以看到一个示例,其中4
映射到以下数组中提供的4个值。您只需要确保数组中的值的顺序与它们的问号对应的正确顺序对齐

如果我们想用一个对象在一个查询中解决这一问题,我们可以给
POST
对象增加一些复杂性,使其包含查询所需的所有信息。使用您的示例,考虑以下内容:

// you could define the following object as we have for this example, or it could be coming right from req.body

let update_payload = {
  table_name = 'users',
  query_field = 'email',
  query_value = 'j.smith.old@example.com',
  job_seeker = {
    username: 'j.smith',
    user_type: 'job_seeker',
    name: 'john smith',
    email: 'j.smith.new@example.com',
    password: 'keyboard_cat_new',
    resume: true,
    resume_date_time: '2109-01-01',
    salary_expectation: 100000
  }
};


connection.query('UPDATE ?? SET ? WHERE ?? = ? ', [update_payload.table_name, update_payload.job_seeker, update_payload.query_field, update_payload.query_value], function(error, results, fields) {
  if (error) throw error;
  console.log(results);
});

// expected console output…

OkPacket {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 0,
  serverStatus: 2,
  warningCount: 0,
  message: '(Rows matched: 1  Changed: 1  Warnings: 0',
  protocol41: true,
  changedRows: 1
}

注意:您会看到有时我使用
,而有时我使用
。这是模块的一项功能,它提供转义以防止SQL注入。根据数据库配置、体系结构、字段类型和个人安全策略的具体情况,在何时何地使用单代码与双代码的必要性会有所不同,需要使用自己的代码库进行测试。

这由
mysqljs
模块为您处理,因此您无需过度思考或过度设计。将insert有效负载作为一个对象提供,其中键与表字段名共享相同的命名。无论您提供什么,都将在插入中使用。如果您不提供字段,它将遵循数据库架构中的表默认值(
id
将自动填充并递增,如果您以这种方式进行设置,
created\u at
timestamp
或其他类似日期字段,如果字段设置为在未提供值时使用默认值,则将使用该默认值)

有关更多详细信息,请参阅此处的文档:

下面是使用您提供的两个场景的示例

var mysql = require('mysql');
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'me',
  password: 'secret',
  database: 'my_db'
});

connection.connect();

let job_seeker = {
  username: 'j.smith',
  user_type: 'job_seeker',
  name: 'john smith',
  email: 'j.smith@example.com',
  password: 'keyboard_cat',
  resume: true,
  resume_date_time: '2109-01-01',
  salary_expectation: 100000
};

let employer = {
  username: 'b.burke',
  user_type: 'employer',
  name: 'betty burke',
  email: 'b.burke@example.com',
  password: 'admin_cat',
  company_name: 'Acme Inc.',
  company_profile: 'http://acme.example.com/about_us/'
};


connection.query('INSERT INTO users SET ?', job_seeker, function(error, results, fields) {
  if (error) throw error;
  console.log(results.insertId);
});

connection.query('INSERT INTO users SET ?', employer, function(error, results, fields) {
  if (error) throw error;
  console.log(results.insertId);
});

// if a scenario exists where you might encounter unique key conflicts, consider using a query model that will update on duplicates:

connection.query('INSERT INTO users SET ? ON DUPLICATE KEY UPDATE', employer, function(error, results, fields) {
  if (error) throw error;
  console.log(results.insertId);
});

// this would update every field provided in the employer object. If you didn't want to update every fields, you'd have to list out only the fields you'd like to update:

connection.query('INSERT INTO users SET ? ON DUPLICATE KEY UPDATE name = VALUES(name)', employer, function(error, results, fields) {
  if (error) throw error;
  console.log(results.insertId);
});

// in the above example, only the name field will be updated if a duplicate is found, even though the full employer object is provided.
如果在将
POST
正文传递到代码中的这一步之前正确地构造了它,那么您可以节省一些时间,只需将它传递到查询函数,而无需额外的工作或对象构造或操作

根据评论进行编辑

如果您的计划包括一些查询参数,您可能希望使用更新而不是插入。无论采用哪种方式,我们都可以将此作为一个示例,说明如何演示
mysqljs
模块提供的动态功能

每次使用
时,它都是一个占位符,映射到函数后面的数组索引

在我链接的文档部分中,您可以看到一个示例,其中4
映射到以下数组中提供的4个值。您只需要确保数组中的值的顺序与它们的问号对应的正确顺序对齐

如果我们想用一个对象在一个查询中解决这一问题,我们可以给
POST
对象增加一些复杂性,使其包含查询所需的所有信息。使用您的示例,考虑以下内容:

// you could define the following object as we have for this example, or it could be coming right from req.body

let update_payload = {
  table_name = 'users',
  query_field = 'email',
  query_value = 'j.smith.old@example.com',
  job_seeker = {
    username: 'j.smith',
    user_type: 'job_seeker',
    name: 'john smith',
    email: 'j.smith.new@example.com',
    password: 'keyboard_cat_new',
    resume: true,
    resume_date_time: '2109-01-01',
    salary_expectation: 100000
  }
};


connection.query('UPDATE ?? SET ? WHERE ?? = ? ', [update_payload.table_name, update_payload.job_seeker, update_payload.query_field, update_payload.query_value], function(error, results, fields) {
  if (error) throw error;
  console.log(results);
});

// expected console output…

OkPacket {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 0,
  serverStatus: 2,
  warningCount: 0,
  message: '(Rows matched: 1  Changed: 1  Warnings: 0',
  protocol41: true,
  changedRows: 1
}
注意:您会看到有时我使用
,而有时我使用
。这是模块的一项功能,它提供转义以防止SQL注入。根据数据库配置、体系结构、字段类型的具体情况