“错误”:“invalid input value for enum”仅在应用程序中使用 pg 包执行 INSERT SQL 操作时

Posted

技术标签:

【中文标题】“错误”:“invalid input value for enum”仅在应用程序中使用 pg 包执行 INSERT SQL 操作时【英文标题】:"Error": "invalid input value for enum" only when using pg package in application to do INSERT SQL operation 【发布时间】:2019-12-23 08:34:22 【问题描述】:

我开始构建我的应用程序的用户身份验证部分,并且我使用 PostgreSQL 作为我的数据库。我在 PG 中使用以下代码设置了一个表。这是我用来设置USERS 表的代码。当我在psql 控制台中执行INSERTS 时,一切正常。但是,当我在使用 pg npm 包并通过客户端实例查询数据库的 NodeJS 应用程序中执行此操作时,无法正常工作。

  DROP EXTENSION IF EXISTS pgcrypto;
  DROP TYPE IF EXISTS genderEnum;
  DROP TYPE IF EXISTS roleEnum;
  -----------------------------------------------

  CREATE OR REPLACE FUNCTION trigger_set_timestamp()
  RETURNS TRIGGER AS $$
  BEGIN
      NEW.updated_at = NOW();
      RETURN NEW;
      END;
  $$ LANGUAGE plpgsql;

  -----------------------------------------------
  DROP EXTENSION IF EXISTS pgcrypto;
  CREATE EXTENSION pgcrypto;

  -----------------------------------------------

  CREATE TYPE genderEnum AS ENUM ('male', 'female', 'other');
  CREATE TYPE roleEnum AS ENUM ('banned', 'suspended', 'member', 'admin', 'developer');

  -----------------------------------------------
  CREATE TABLE users
  (
  id            serial       NOT NULL PRIMARY KEY,
  username      varchar(33)  NOT NULL UNIQUE,
  password      varchar(255) NOT NULL,
  date_of_birth date         NOT NULL,
  gender        genderEnum   NOT NULL,
  created_at    timestamptz  NOT NULL DEFAULT NOW(),
  updated_at    timestamptz  NOT NULL DEFAULT NOW(),
  role          roleEnum     NOT NULL DEFAULT 'member',
  description   text,
  image         jsonb,
  friends       jsonb
  );

  -----------------------------------------------
  CREATE TRIGGER set_timestamp
  BEFORE UPDATE ON users
  FOR EACH ROW
  EXECUTE PROCEDURE trigger_set_timestamp();

命令行(成功)尝试:

INSERT INTO USERS ( username, password, date_of_birth, gender, role, description, friends ) VALUES ( 'Amy', '123456', '02/24/1975', 'female', 'member', 'I am a fun girl.', '["Jack", "Suzie"]' );


INSERT 0 1


SELECT * FROM USERS WHERE username = 'Amy';


 id | username | password | date_of_birth | gender |          created_at           |          updated_at           |  role  |   description    | image |      friends
----+----------+----------+---------------+--------+-------------------------------+-------------------------------+--------+------------------+-------+-------------------
  9 | Amy      | 123456   | 1975-02-24    | female | 2019-08-17 03:19:34.518501-04 | 2019-08-17 03:19:34.518501-04 | member | I am a fun girl. |       | ["Jack", "Suzie"]
(1 row)


NodeJS 代码(不成功)尝试

以下是我目前用于此查询的 NodeJS 代码。我有一个包含在 POST 方法中的 async/await 函数。我正在解构 req.body 中的值,然后将它们作为参数插入到 SQL 查询中以代替 $1, $2, $3...etc,以及 NON 所需的值(如 descriptionimagefriends),我有一个类似friends||null 的声明作为预防措施(我不是100% 肯定需要)。我也有一些原始的错误处理正在进行,但这只是为了让我有一些 atm。到时候我会更新它,它对应用程序更重要。

router.post("/register", async (req, res) => 

  const date = new Date();
  const loggableDate = date.toLocaleDateString();
  const loggableTime = date.toLocaleTimeString();

  const  username, password, date_of_birth, gender, role, description, image, friends  = req.body;

  console.log("\nBODY", req.body, "\n");

  try 
    const user = await database.query(`INSERT into 
    USERS (
      username, 
      password, 
      date_of_birth, 
      gender, 
      role, 
      description, 
      image, 
      friends
    ) 
    VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, [
        [username],
        [password],
        [date_of_birth],
        [gender],
        [role],
        [description || null],
        [image || null],
        [friends || null]
      ]
    );

    if (!user) 
      return res.status(404).json( message: errors.clientSideError404, date: loggableDate, time: loggableTime );
    

    return res.status(200).json(newUser.rows[0]);

   catch (error) 

    return res.status(500).json( error: error.stack, date: loggableDate, time: loggableTime );

  
);

以上NodeJS代码的结果:



    "error": "error: invalid input value for enum genderenum: \"\"female\"\"\n    at Connection.parseE (/Users/JON-DOE/Desktop/virtual-desktop/Work/app/node_modules/pg/lib/connection.js:604:11)\n    at Connection.parseMessage (/Users/JON-DOE/Desktop/virtual-desktop/Work/app/node_modules/pg/lib/connection.js:401:19)\n    at Socket.<anonymous> (/Users/JON-DOE/Desktop/virtual-desktop/Work/app/node_modules/pg/lib/connection.js:121:22)\n    at Socket.emit (events.js:203:13)\n    at addChunk (_stream_readable.js:294:12)\n    at readableAddChunk (_stream_readable.js:275:11)\n    at Socket.Readable.push (_stream_readable.js:210:10)\n    at TCP.onStreamRead (internal/stream_base_commons.js:166:17)",
    "date": "8/17/2019",
    "time": "3:44:51 AM"


当我在 PostMan 上插入以下对象时(选择原始数据按钮,应用程序/JSON 设置为文本类型)。


    "username": "Amy",
    "password": "123456",
    "date_of_birth": "02/24/1957",
    "gender": "female",
    "role": "member",
    "description": "I am a fun girl",
    "friends": ["Jack", "Suzie"]

我希望找出我在使用这种枚举器类型时做错了什么。我认为这与我使用 PostMan 输入数据的方式有关,因为 psql 控制台工作得很好。如果这篇文章冗长,请原谅我。我对后端编程相当陌生,所以我在这里吸收了很多信息,非常感谢有人的帮助。只是为了记录,用户的密码将使用 bCryptJS 和 JWT 加密,但现在,我只是想让一个简单的 INSERT 工作!!

谢谢!

【问题讨论】:

【参考方案1】:

取消引用后您的错误:

error: invalid input value for enum genderenum: ""female""

您尝试插入的值似乎不是female,而是"female"。观察:

=> create temporary table test (a genderEnum);
=> insert into test values ('female');
INSERT 0 1
=> insert into test values ('"female"')
ERROR:  invalid input value for enum genderenum: ""female""

所以看起来你的数据不是你想象的那样。

【讨论】:

数据似乎就在查询之外。就像查询将其添加到 JSON 字符串化对象一样。这是进入查询之前的 console.log。 BODY username: 'Amy', password: '123456', date_of_birth: '02/24/1957', gender: 'female', role: 'member', description: 'I am a fun girl', friends: [ 'Jack', 'Suzie' ] 我想知道是否是参数化输入导致了这个问题,b/c 当我用字符串文字内联 SQL 变量时我可以执行 INSERT,但这会使我的应用程序面临风险不幸的是,SQL 注入 :( 我会尝试创建一个 SSCCE 以仅连接到数据库并执行插入以查看这是否有效。我不是 NodeJS 开发人员,我很难做到。 我决定从我的数据库中删除枚举类型,因为要么我没有正确使用 Node 来处理它们,要么它们在我使用的 pg gem 中没有按预期工作设置我的配置,顺便说一句,就像const Client = require("pg"); const client = new Client( connectionString: process.env.DATABASE_URL || process.env.PG_CONNECTION_STRING ); client.connect(); 一样。我将以编程方式将列类型分配给varchar,并以编程方式验证输入(如if (validate(gender)) // continue else throw new Error("error message")) 您可以通过添加检查约束获得枚举提供的相同数据库实施/验证。例如验证性别只是“更改表用户添加约束 validate_gender 检查(性别在('男性','女性','其他'));”这将自动验证,不需要您以编程方式验证。

以上是关于“错误”:“invalid input value for enum”仅在应用程序中使用 pg 包执行 INSERT SQL 操作时的主要内容,如果未能解决你的问题,请参考以下文章

Pig 安装错误:错误 pig.Main:错误 2998:未处理的内部错误

Informix 错误:发生了语法错误。错误代码:-201

我收到一个错误:“MetaMask - RPC 错误:错误:错误:[ethjs-rpc] rpc 错误与有效负载”

错误精灵错误跟踪器错误

网页打开显示错误500是啥意思

PHP错误处理