首页 > 解决方案 > SQL WHERE NOT EXISTS with string conditional

问题描述

我正在尝试使用如下子查询检查我的数据库 (MySQL, Node.js) 中是否不存在电子邮件:

register: async (data) => {

const rows = await db.promise().execute(

INSERT INTO Users (userEmail, userPassword) 
    SELECT * 
    FROM 
        (SELECT ${data.userEmail}, ${data.userPassword}) AS tmp
    WHERE 
        NOT EXISTS (SELECT userEmail, userPassword 
                    FROM Users 
                    WHERE userEmail = {data.userEmail}) 
    LIMIT 1;

 );
      return rows;
    },

但它不起作用

我已经在尝试这个 id 类型为 INT 的请求。

我的问题是:你认为这个请求可以用字符串类型吗?

非常感谢 !

如果我向已经在我的数据库上注册的用户提出请求,我会收到此错误:

{

"error": {
    "message": "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@beevora.fr, $2b$10$JnEjg8GIVXbJDAeGnm7ESey27yXkHMcvh2b/SKRQ.6UH5Tpvv.OVG\n      ' at line 2",
    "code": "ER_PARSE_ERROR",
    "errno": 1064,
    "sqlState": "42000",
    "sqlMessage": "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@beevora.fr, $2b$10$JnEjg8GIVXbJDAeGnm7ESey27yXkHMcvh2b/SKRQ.6UH5Tpvv.OVG\n      ' at line 2"
},
"errMessage": "500 error server"

}##

如果用户还不存在:

{

"error": {
    "message": "Unknown column 'Lorris' in 'field list'",
    "code": "ER_BAD_FIELD_ERROR",
    "errno": 1054,
    "sqlState": "42S22",
    "sqlMessage": "Unknown column 'Lorris' in 'field list'"
},
"errMessage": "500 error server"

}##

标签: sqlstringintegerwhere-clauseexists

解决方案


是的,这是可能的,并且不依赖于您的类型 - 字符串或整数。它与 int 一起使用,因为您发送查询:

select 1 

对于 sql 这意味着必须插入 1 作为 int 类型如果您设置字符串,则将查询发送到数据库选择,如下所示:

select mymail@gmail.com 

数据库了解名称为 mymail@gmail.com 的选择列应该搜索列 mymail@gmail.com - 它没有找到任何列。

正确的是:

 select 'mymail@gmail.com'

和 ''

但是将用户的原始值插入到查询中是错误的 - 您将有 SQL 注入漏洞,任何熟悉此注入的人都可以访问任何数据并将任何内容插入到您的数据库中。您可以在SQL 注入 wikipedia上阅读更多信息

为了使这项工作正常,你应该

  1. 创建对电子邮件具有唯一约束的表,如下所示
CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  email VARCHAR(256) NOT NULL UNIQUE,
  password_hash VARCHAR(256)
)

您需要 id 来引用其他表,我建议您不要存储原始密码,而是存储哈希(例如 sha-1),以防止在访问您的数据库时窃取密码 2. 像这样进行查询

dbconn.query("INSERT INTO USERS (email, password_hash) VALUES (?,?)",
            [email, passwordHash], (err, result) => {
 if(err){
   //1169 or 1062 error code. See error reference below
   if(err.code == DUPLICATE_ERROR_CODE){ 
     notifyUserThatEmailExists();
     return;
   } else {
     throw err;
   }
   success();
 } 
}

错误参考 MySQL

在此示例中,电子邮件和密码哈希参数将设置为参数,并且始终由数据库解释为参数,而不是列名,并且此查询将受到 SQL 注入保护


推荐阅读