【问题标题】:pg_get_serial_sequence not recognizing table namepg_get_serial_sequence 无法识别表名
【发布时间】:2019-12-23 15:25:21
【问题描述】:

我正在尝试通过在过程中使用pg_get_serial_sequence() 在表中创建最后一个SERIAL ID,但我不断收到错误:

[42P01]错误:关系“用户”不存在

其中:SQL 函数“insert_new_user”语句 2

User 表肯定存在,我可以从中 SELECT

以下是用于创建受我的函数影响的 2 个表的 DDL 脚本:

CREATE TABLE users.User
(
    ID SERIAL PRIMARY KEY,
    Name TEXT NOT NULL UNIQUE,
    EmailAddress TEXT,
    ROWCREATE_TS TIMESTAMP,
    IS_ACTIVE BOOLEAN,
    INACTIVE_TS TIMESTAMP
);

CREATE TABLE users.Credential
(
    CredentialValue TEXT,
    UserId INT REFERENCES users.User(ID)
);

这是返回错误的过程:

/**
  Creates a new user
 */
CREATE OR REPLACE PROCEDURE users.INSERT_NEW_USER(userName TEXT, emailAddress TEXT, password TEXT)
LANGUAGE SQL
AS $$
    INSERT INTO users.User
    (
        NAME,
        EmailAddress,
        ROWCREATE_TS,
        IS_ACTIVE
    )
    SELECT
        INSERT_NEW_USER.userName,
        INSERT_NEW_USER.emailAddress,
        CURRENT_TIMESTAMP,
        TRUE
    WHERE
        NOT EXISTS(
            SELECT TRUE
            FROM users.User
            WHERE
                NAME = INSERT_NEW_USER.userName
        );

    INSERT INTO users.Credential
    (
        CREDENTIALVALUE,
        USERID
    )
    VALUES
    (
        INSERT_NEW_USER.password,
        (SELECT currval(pg_get_serial_sequence('user', 'id')))
    );
$$;

(注意:在有人提及之前 - 我不打算在此处以纯文本形式存储密码。)

我可以做些什么不同的事情来解决pg_get_serial_sequence 无法识别User 表的问题,或者最终将最后创建的ID 存储到一个可用变量中,我可以将它传递到我的INSERT INTO users.Credential 语句中?

【问题讨论】:

  • user 我们保留关键字。你需要引用它:"User" - 但如果你找到一个不同的名字会更好
  • "user" 是 PostgreSQL 中的保留关键字。您可以拥有名为“user”和“User”的表和列,但您必须始终将这些名称双引号并始终使用相同的大小写。最好完全避免它们。
  • 感谢您的建议。正如@clamp 建议的那样,重命名表是不够的,我还必须使用完全限定的名称。我之前用名为User 的表尝试过这个,但仍然没有成功。因此,再次重命名表并使用完全限定路径解决了问题。

标签: sql postgresql syntax sql-insert auto-increment


【解决方案1】:

通过使用 cmets 中的建议组合解决了这个问题。

我已经重命名了表,因为User 是 PostgreSQL 关键字,并且还在 pg_get_serial_sequence() 调用中使用了完全限定名称 users.NewTableName,如下所示。

SELECT currval(pg_get_serial_sequence('users.NewTableName', 'id')).

编辑:对于有类似问题的未来读者来说,值得指出的是,以下内容也可以解决我将 ID 降低到第二个语句的目标。我可以使用WITH

CREATE OR REPLACE PROCEDURE users.INSERT_NEW_USER(userName TEXT, emailAddress TEXT, password TEXT)
LANGUAGE SQL
AS $$
    WITH Inserted as(
        INSERT INTO users.Users
        (
            NAME,
            EmailAddress,
            ROWCREATE_TS,
            IS_ACTIVE
        )
        SELECT
            INSERT_NEW_USER.userName,
            INSERT_NEW_USER.emailAddress,
            CURRENT_TIMESTAMP,
            TRUE
        WHERE
            NOT EXISTS(
                SELECT TRUE
                FROM users.Users
                WHERE
                    NAME = INSERT_NEW_USER.userName
            )
        RETURNING ID
    )

    INSERT INTO users.Credential
    (
        CREDENTIALVALUE,
        USERID
    )
    VALUES
    (
        INSERT_NEW_USER.password,
        (SELECT Inserted.ID FROM Inserted)
    );
$$;

话虽如此,我也想提醒读者,他们应该避免使用 PostgreSQL 关键字来命名表、变量等。

【讨论】:

    猜你喜欢
    • 2015-11-10
    • 1970-01-01
    • 2016-09-16
    • 2019-01-16
    • 2019-08-05
    • 2010-10-05
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多