【问题标题】:Handling Postgres Error Message To Perform Correct Query处理 Postgres 错误消息以执行正确查询
【发布时间】:2016-11-24 09:32:02
【问题描述】:

我正在使用pgnode.js。当用户使用auth0 小部件登录时,我将传递它返回的电子邮件并检查我的数据库以查看用户是否存在。如果用户不存在,我将它们插入数据库。我已经设法通过一项功能的黑客工作来解决这个问题,但我希望能得到一些帮助来解决它。

我面临的问题。

  1. 检查数据库中的电子邮件时,它不是检查整个电子邮件地址。

    var emailCheck = "SELECT id from public.user WHERE email=" + req.body.email;

    req.body.email;实际上是myemail@example.com

返回此错误,

column "myemail" does not exist

虽然

myemail@example.com

确实存在。

  1. 无论它抛出什么错误,它都会继续插入电子邮件地址。如果它不存在,则将其插入。由于电子邮件上有唯一密钥,因此会引发错误

    重复键值违反唯一约束“uk_user_email”

所以要解决这个问题,我的问题是为什么它不在 @ 符号之后检查?我应该遵循什么逻辑来更改此函数以运行第一个查询并且仅在第一个查询未找到相关电子邮件地址时才运行第二个查询?

checkRegister: function(req, res) {
            pool.connect(function(err, client, done) {
                if (err) {
                    return console.error('error fetching client from pool', err);
                } connection
                var emailCheck = "SELECT id from public.user WHERE email=" + req.body.email;
                var emailInsert = "insert into public.user (user_auth_level,email,account_locked,contract) " +
                    "values ('1','" + req.body.email + "','false','false')"
                client.query(emailCheck, function(err, result) {
                    if (err) {
                        return console.error(err.message);
                    }

                });
                client.query(emailInsert, function(err, result) {
                    if (err) {
                        return console.error(err.message);
                    }

                });
                done(); 
            });
            pool.on('error', function(err, client) {
                console.error('idle client error', err.message, err.stack)
            }); 
        } 

【问题讨论】:

    标签: node.js postgresql angular node-postgres


    【解决方案1】:

    您需要用 ' 包装您的值以使其成为字符串。如果没有字符串换行,它将在列之间进行比较。应该是:

    var yourQuery = "SELECT id from public.user WHERE email=" + req.body.email; // SELECT id from public.user WHERE email=myemail@example.com
    var correntQuery = "SELECT id from public.user WHERE email='" + req.body.email + "'"; // SELECT id from public.user WHERE email='myemail@example.com'
    

    Nodejs 是同步的,您需要使用回调或承诺来链接您的代码,如下所示:

    checkRegister: function (req, res) {
        pool.connect(function (err, client, done) {
            if (err) {
                console.error(err);
                // should return response error like 
                return res.status(500).send();
            }
            var emailCheck = "SELECT id from public.user WHERE email=$1";
            client.query(emailCheck, [req.body.email], function (err, result) {
                if (err) {
                    console.error(err);
                    res.status(500).send();
                    return done(); // always close connection
                }
                if (result.rowCount > 0) {
                    let user = result.rows[0]
                    // return your user
                    return done(); // always close connection
                } else {
                    var emailInsert = "insert into public.user (user_auth_level, email, account_locked, contract) " +
                        "values ('1', $1,'false','false') RETURNING *"
                    client.query(emailInsert, [req.body.email], function (err, result) {
                        if (err) {
                            console.error(err);
                            res.status(500).send();
                            return done(); // always close connection
                        } else {
                            if (result.rowCount > 0) {
                                let user = result.rows[0]
                                // return your user
                                return done(); // always close connection
                            }
                        }
    
                    });
                }
            })
        })
        pool.on('error', function (err, client) {
            console.error('idle client error', err.message, err.stack)
        });
    } 
    

    【讨论】:

    • 我的另外 2 美分,总是更好地使用准备好的语句而不是 concat 查询字符串,以获得更好的安全性和控制,如自动转义和数据类型检测。请参阅我上面的更新答案
    • 如果我要添加 5 个值,请您向我解释一下 $1 是否知道 $1 是第一个变量项,如果有第二个变量项,请使用 $2?如果不是这样,那它是如何工作的?
    【解决方案2】:

    对于#1,问题在于您没有引用输入值。由于(我假设)您可能不想担心引用/转义/等您自己的值,我会考虑使用parameterized queries。这将有助于保护您免受 sql 注入(并且您当前的代码非常容易受到这种情况的影响)。

    对于#2,它实际上并没有“抛出”那个错误。该方法是异步的,并将错误提供给回调。如果您想“按顺序”运行查询,则需要执行以下操作:

    client.query(emailCheck, function(err, result) {
      if (err) {
        // should probably do `return done(err);` here
        return console.error(err.message);
      }
      client.query(emailInsert, function(err, result) {
        if (err) {
          // same thing - probably need done(err) in here
          return console.error(err.message);
        }
        return done();
      });
    });
    

    注意调用是如何嵌入到彼此“内部”的(特别是在回调内部)。

    【讨论】:

    • 嘿,非常感谢!这一直在杀死我。我不明白你说的第一名是什么意思。它可以很好地插入完整的电子邮件。为什么不检查整个电子邮件?我看不出检查它是否存在和插入它之间有什么区别。
    • 哦,在您的 check 查询中,您没有在电子邮件周围加上单引号 ' - 因此 postgres 的查询解析器遇到错误。这就是第一个错误的来源。
    猜你喜欢
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-12
    相关资源
    最近更新 更多