【问题标题】:Add serial value across multiple tables跨多个表添加序列值
【发布时间】:2014-07-09 00:06:23
【问题描述】:

我的 Postgres 数据库中有以下两个表:

CREATE TABLE User (
    Id       serial UNIQUE NOT NULL, 
    Login    varchar(80) UNIQUE NOT NULL,
PRIMARY KEY (Id,Login)
);

CREATE TABLE UserData (
    Id       serial PRIMARY KEY REFERENCES Users (Id),
    Password varchar(255) NOT NULL
);

假设我添加了一个新用户INSERT INTO Users(Id, Login) VALUES(DEFAULT, 'John'),并且还想在UserData 中添加VALUES(id, 'john1980'),其中id 是John 的新ID。

我如何获得该 ID?对刚刚创建的东西运行查询似乎是多余的。我在整个数据库中有多种这样的情况。也许我的设计总体上存在缺陷?

(我显然不会那样存储密码。)

【问题讨论】:

    标签: sql postgresql database-design primary-key common-table-expression


    【解决方案1】:

    1) 修复您的设计

    CREATE TABLE usr (
        usr_id serial PRIMARY KEY,
       ,login  text UNIQUE NOT NULL
    );
    
    CREATE TABLE userdata (
        usr_id   int PRIMARY KEY REFERENCES usr
       ,password text NOT NULL
    );
    
    • 从阅读the manual about identifiers and key words开始。

      • userreserved word。切勿将其用作标识符。
      • 使用描述性标识符。 id 没用。
      • 避免混合大小写标识符。
    • serial 用于可单独进行 pk 的唯一列。无需多列 pk。

    • 引用userdata.usr_id 也不能是连续的。使用普通的integer

    • 我只是使用text 而不是varchar(n),这是可选的。 More here.

    • 您可以考虑将两个表合并为一个...

    2) 在两者中查询到 INSERT

    键是RETURNING clause,可用于INSERTUPDATEDELETE,以立即从当前行返回值。
    最好在data-modifying CTE 中使用:

    WITH ins1 AS (
       INSERT INTO usr(login)
       VALUES ('John')             -- just omit default columns
       RETURNING usr_id            -- return automatically generated usr_id
       )
    INSERT INTO userdata (usr_id, password )
    SELECT i.usr_id, 'john1980'
    FROM   ins1 i;
    

    【讨论】:

      【解决方案2】:

      您可以考虑使用触发器。新插入行的 Id 列可以通过名称 NEW.Id 访问。

      参考文献

      1. CREATE TRIGGER documentation on PostgreSQL Manual
      2. Trigger Procedures

      【讨论】:

        猜你喜欢
        • 2021-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多