引用序列时出错:“关系\”<sequence>\“不存在”

问题描述 投票:0回答:1

我正在使用 PostgreSQL 中的序列在 Typescript 中执行如下 Upsert:

let SAVE_CUSTOMER = `
INSERT INTO "db"."customers" ("id", "name")
VALUES (NEXTVAL('customers_sq'), $1)
ON CONFLICT ("id") DO UPDATE
  SET "name" = $1;
`;


function saveCustomer(name: string) {
  datasource.query(SAVE_CUSTOMER, name)
}

地点:

  • “db”是数据库的名称
  • “customers”是表的名称
  • “id”是表中的主键
  • “名称”是表中的另一列

我收到以下错误消息:

error: i: relation \"customers_sq\" does not exist

我尝试过的事情也不起作用:

  • 更新为
    NEXTVAL('db'.'customers_sq')
  • 更新为
    NEXTVAL("db"."customers_sq")
  • 更新为
    NEXTVAL("customers_sq")

我可以在 Postgres 数据库查看器中看到该序列(也是全部小写)。有关如何调试的任何提示?

postgresql identifier upsert nextval
1个回答
0
投票

函数

nextval()
需要一个regclass类型的
单个参数
,这是一种“对象标识符类型”,基本上是基本数据类型
oid
的别名。 说明书:

按命名空间分组的对象的所有 OID 别名类型 接受模式限定名称,并将显示模式限定名称 如果在当前搜索路径中找不到该对象,则在输出中 没有资格。例如,

myschema.mytable
是可以接受的 输入
regclass
(如果有这样的表格)。该值可能是 输出为
myschema.mytable
,或只是
mytable
,具体取决于 当前搜索路径。

因此,如果您的模式名称是

db
并且序列名称是
customers_sq
- 都是令人惊讶的选择! - 那么这是正确的调用:

SELECT nextval('db.customers_sq')

如果涉及任何“非法”名称,则需要用双引号引起来。参见:

如何调试?

如果涉及到列所拥有的

SQUENCE
serial
IDENTITY
列就是这种情况),请使用函数
pg_get_serial_sequence(table text, column text)
获得明确的答案:

SELECT pg_get_serial_sequence('db.customers', 'id');

结果经过适当格式化以传递给序列函数。

要测试给定名称的对象是否存在,而不烧录序列号,请尝试以下之一:

SELECT 'db.customers_sq'::regclass;
SELECT to_regclass('db.customers_sq');

如果对象不存在,第一个会引发异常,第二个仅返回 null。准确地说,该名称可能解析为任何类似表格的对象:表、视图等。为了确保它存在并且是一个序列:

SELECT *
FROM   pg_catalog.pg_class c
JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE  n.nspname = 'db'            -- schema name
AND    c.relname = 'customers_sq'  -- sequence name
AND    c.relkind = 'S'             -- is type sequence

或者,对于一个简短的布尔答案:

SELECT EXISTS (
   SELECT FROM pg_catalog.pg_class c
   WHERE  c.relnamespace = 'db'::regnamespace  -- schema name
   AND    c.relname = 'customers_sq'  -- sequence name
   AND    c.relkind = 'S'             -- is type sequence
   );

参见:

© www.soinside.com 2019 - 2024. All rights reserved.