【问题标题】:Usage of 'skip' option in multi-row update在多行更新中使用“跳过”选项
【发布时间】:2019-10-02 16:34:29
【问题描述】:

我是 NodeJs 的新手,并尝试使用 pg-promise 对我的 PG 数据库执行所有请求。 我希望能够动态更新列,这意味着有时我只会更新一行的两列,有时我会更新所有列,等等...... 我的输入将是 JSON。

因为我希望端点能够更新多行,所以我尝试使用带有 ColumnSet 的 helpers 命名空间。

这是我的 Javascript 代码(灵感来自之前的 stackoverflow 答案):

  /* logic for skipping columns: */
  const skip = c => !c.exists || c.value === undefined;
  
  /* all the columns of the table */
  const column_structure = new dbconfig.pgp.helpers.ColumnSet(
  [ '?id',
    {name: 'firstname', skip}, 
    {name: 'surname', skip}, 
    {name: 'yob', skip}, // year of birth
    {name: 'defensive_skill', skip}, 
    {name: 'offensive_skill', skip}, 
    {name: 'login', skip}, 
    {name: 'password', skip}
  ],
     {table: 'players'});

这是我提供给端点的 JSON:

[{
  "id" : 25,
  "firstname": "Stephen",
  "surname": "Harrison",
  "yob": 1991,
  "defensive_skill": 5,
  "offensive_skill": 3,
  "login": "harry",
  "password": "123456"
},
{
  "id": 26,
  "firstname": "Chris",
  "surname": "Jackson",
  "defensive_skill": 5,
  "offensive_skill": 4,
  "login": "chris",
  "password": "123456"
}
]

这是错误:

Property 'yob' doesn't exist.

如您所见,在我的数组的第二个对象中,我没有指定字段“yob”。 我期待对于第二个对象,除了“yob”之外的所有列都将被更新。 是不是我做错了什么?

【问题讨论】:

  • 你是插入一个有列的表还是只是一个 json/jsonb 的列?大概如果这是一个表关系,它会告诉您yob 列不存在,需要添加。
  • @Lucas 总共有八列,更新时我希望能够单独更新每一列。没有“json/jsonb 列”。我认为我的问题与“pg-promise”有关。
  • 更正了 skipCB 类型的无效使用,从 c => !c.exists || c === undefined;c => !c.exists || c.value === undefined;

标签: javascript node.js postgresql express pg-promise


【解决方案1】:

它不起作用的原因是因为skip 逻辑只能用于单行更新,如documented in the API

由方法 update 使用(用于单个对象)...

多行更新语法不允许任何跳过逻辑,因此您需要在属性缺失时提供默认值,如下所示:

{name: 'yob', skip, def: defaultValue}

defaultValue 可以是上面的任何东西,包括undefined

或者,您可以使用属性init,并动态返回值。


所以在上面的代码中,如果你把列声明改成这样:

{name: 'yob', skip, def: null}

您的update 呼叫将生成:

UPDATE "players" AS t SET "firstname"=v."firstname","surname"=v."surname","yob"=v."yob","defensive_skill"=v."defensive_skill","offensive_skill"=v."offensive_skill","login"=v."login","password"=v."password" FROM (VALUES(25,'Stephen','Harrison',1991,5,3,'harry','123456'),(26,'Chr
is','Jackson',null,5,4,'chris','123456')) AS v("id","firstname","surname","yob","defensive_skill","offensive_skill","login","password")

从生成的 SQL 中可以看出,使用这种语法不可能跳过一列,这就是为什么 skip 在多行更新时被忽略的原因。如果您一次传入一个对象,您可以看到它的工作原理,但这与您正在寻找的使用场景不同。

【讨论】:

  • 感谢您的准确回答,我将一次更新一行,这似乎是最适合我的解决方案,因为我不想设置默认/初始化值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-17
  • 1970-01-01
  • 2016-06-13
  • 2021-10-18
  • 2017-04-03
  • 2014-01-01
相关资源
最近更新 更多