如何使用参数化输入将 NULL 值从 nodeJS/javascript 插入 MySQL?

Posted

技术标签:

【中文标题】如何使用参数化输入将 NULL 值从 nodeJS/javascript 插入 MySQL?【英文标题】:How to insert NULL value from nodeJS/javascript to MySQL using parameterized inputs? 【发布时间】:2019-06-29 11:09:36 【问题描述】:

如何使用参数化输入确保插入数据库的值实际上是 NULL 值而不是“NULL”或空字符串?

注意:这是从一个问题修改为更多的教程。

【问题讨论】:

【参考方案1】:

使用 'mariadb/callback' 作为数据库的连接器:

const db = require('mariadb/callback');

mariaDB 是 mysql 数据库的一种选择。

让我们使用以下作为示例变量:

var customName = '    ';
var someAddress = 'this is an address';
var mainID = 'some unique ID';
var secondID = 'maybe not a unique ID';

查询参数化如下:

var sql = `UPDATE myTable SET myName=?, myAddress=? WHERE _id=? AND otherID=?;`;

通过使用“?”字符而不是变量名不仅可以简化 SQL 语句,而且更重要的是可以防止 SQL 注入。具体来说,如果其中一个变量存储了这个:

var id = '42 OR 1=1;'

在这种情况下不使用参数化输入的结果可能会导致整个表更新为相同的名称和地址。使用参数化输入只会导致此操作失败,因为数据库中的任何 id 都不会是“42 OR 1=1”。

现在,如果 customName 是空字符串或空格,甚至是“NULL”字符串,您可以这样做:

customName = customName.trim();
if ( (customName === '') || (customName.toUpperCase() === 'NULL') ) 
  customName = null;

等同于:

if ( (customName.trim() === '') || (customName.trim().toUpperCase() === 'NULL') ) 
  customName = null;

(第一个版本只是简单地重新分配 customName 而没有任何前导/尾随空格 - 确保在选择此方法时不需要保留字符串的值)

.trim() 将删除字符串两端的所有空格(它不会删除任何非空格字符之间的任何空格)。

.toUpperCase() 会将字符串更改为所有大写字符,这样如果字符串为“null”或“Null”或任何其他包含任何小写字符的变体,在评估“NULL”时它仍将评估为“true” ' 平等。请注意,在这里使用.trim() 也很重要,这样

'  nuLl  '

变成

'NULL'

并且仍然评估为“真”。

接下来,我们需要创建值数组:

var values = [customName, someAddress, mainID, secondID];

最后是db查询:

db.query(sql, values, (err, result) => 
  // callback stuff to do here

db 指的是在本文开头创建的连接器。我没有包括实际的连接过程,因为这超出了本文的范围。作为参考,documentation for the API is here。

连接数据库后,db.query 用于执行查询。第一个参数“sql”是参数化的 SQL 语句。第二个参数“values”是将在查询中使用的值数组。此数组的顺序必须与它们的使用顺序相同。

作为不该做什么的例子:

var sql = `UPDATE myTable SET myName=$customName, myAddress=$someAddress WHERE _id=$mainID AND otherID=$secondID;`;

这不好的原因是因为 SQL 注入,它的工作原理如下: 你首先这样做:

var customName = 'same name';
var mainID = '" OR ""="';
var secondID = '" OR ""="';

生成的 sql 代码将是:

var sql = `UPDATE myTable SET myName="same name", myAddress="this is an address" WHERE _id="" OR ""="" AND otherID="" OR ""="";`;

结果是现在数据库中的每个条目都具有相同的名称和相同的地址。

此 SQL 注入示例修改自 W3 schools。

【讨论】:

由于这似乎是与问题中提出的内容无关的“用户错误”,我建议删除问题。 或者,重写问题以包含关于何时NULL 真正为空的教程,而不是字符串"NULL",并指出可以将一个转换为另一个的方法。 如果您正确设计了问题,您可以“自我回答”并获得批准答案的积分。但是,请不要把它说成“哎呀,我搞砸了”。 肯定是用户错误。感谢您的建议,我一直在努力成为一个更好的溢出者。我将很快重新审视它,使其更像教程。与此同时,我正在添加一个编辑以澄清这个问题不需要更多答案。 (另外,没有注意到“删除”选项,很高兴知道!) 以上 cmets 参考了该问题的第一个版本,此答案已被修改,因此上述 cmets 可能不再具有上下文意义。【参考方案2】:

你试试INSERT INTO mytable VALUES ('', NULLIF('$customName',''))怎么样

这里还有一些其他资源,它们似乎也有类似的问题,Set value to NULL in MySQL, How to update column with null value, Set value to NULL in MySQL

现在我想起来你可能只需要更改customName = "NULL"

【讨论】:

谢谢。不幸的是,您链接到的所有帖子都没有处理参数化输入;这个问题专门关于如何使用参数化输入插入空值。使用“NULL”字符串肯定会插入一个字符串,而我描述的方法是 javascript 中的实际 null 值,但同样,它被 mariadb 库转换为字符串。 注意:这个答案是对原始问题的回应,因为我已经更新了问题,所以我没有上下文意义。【参考方案3】:

您必须创建第二个表并仅在 myname!==Null 时填写该表

select mytable t1 left join mytablewithvalidnames t2 on t1.id=t2.id

这样 t2.myname 将为 Null

【讨论】:

在这种情况下,我认为这不是一个好的解决方案。由于我只对空值感兴趣,因此不需要第二个表。这也使实际的 SQL 语句本身复杂化到超出实现我想要的程度所必需的程度。我可以简单地创建一个条件,使用 NULL 关键字创建不同版本的 SQL 语句,这将插入实际的 NULL 值,但这不使用参数化输入,这是我想要做的。不过,感谢您的建议。 试试二进制数据类型,或者其他数据类型也许你可以插入NULL。在很多情况下,我使用不同的数据类型来获得我想要的结果。【参考方案4】:

?有同样的问题, 解决方法很简单, 使用 null 而不是 NULL, 所以在你的情况下

var sql = UPDATE myTable SET myName=?, myAddress=? WHERE _id=? AND otherID=?;;

其中 customName=null;

【讨论】:

以上是关于如何使用参数化输入将 NULL 值从 nodeJS/javascript 插入 MySQL?的主要内容,如果未能解决你的问题,请参考以下文章

如何将值从 django 模板化 html 传递到 ajax

如何将值从节点返回到原点(angular2 请求)

如何将复选框值从 HTML 发送到 Node JS?

将扩展选择参数值从一个作业传递到 Jenkins 管道中的另一个远程作业

如何使用 TypeORM 为 postgres 数据库和 nodejs 使用参数化查询作为应用程序的后端服务器

NodeJS技巧