如何在Postgresql中插入行时自动填充外键

How to automaticaly fill a foreign key when a row is inserted in Postgresql

我目前在 postgres 14 下工作。 我有两个 table 的客户和联系人,我想在 table 联系人中添加新联系人时自动从客户名称中找到 customer_id。

CREATE TABLE customers(
   customer_id INT GENERATED ALWAYS AS IDENTITY,
   customer_name VARCHAR(255) NOT NULL UNIQUE,
   PRIMARY KEY(customer_id)
);

CREATE TABLE contacts(
   contact_id INT GENERATED ALWAYS AS IDENTITY,
   customer_id INT,
   contact_name VARCHAR(255) NOT NULL UNIQUE,
   PRIMARY KEY(contact_id),
   CONSTRAINT fk_customer
      FOREIGN KEY(customer_id) 
      REFERENCES customers(customer_id)
);

INSERT INTO customers(customer_name) VALUES('my_first_customer')

所以从这里我想做类似的事情:

INSERT INTO contacts(customer_id, contact_name ) VALUES('my_first_customer',"thomas")

我想在联系人中得到这个结果 table :

contact_id customer_id contact_name
1 1 "thomas"

我试图创建一个函数来将值从 name 更改为 id,但出现类型错误。 因为类型错误在触发器之前被捕获。这是我的功能

CREATE FUNCTION get_id_fct() 
RETURNS TRIGGER AS $get_id_fct$
DECLARE val_id INTEGER;
BEGIN 
SELECT customer_id INTO val_id FROM customers WHERE customers.customer_id = NEW.customer_id;
NEW.customer_id := val_id; 
RETURN NEW
END
$get_id_fct$  LANGUAGE plpgsql;

CREATE TRIGGER get_id
BEFORE INSERT ON contacts
FOR EACH ROW EXECUTE PROCEDURE get_id_fct();'

他们有办法解决这个问题吗?或我不知道的执行此任务的具体方法? 我是 SQL.

的新手

可以在插入语句中进行子查询

INSERT INTO contacts(customer_id, contact_name ) VALUES (
(select customer_id from customers where customer_name = 'my_first_customer') ,'thomas');

如果有多个具有给定名称的客户,此查询将失败,如果没有具有给定名称的客户

,则为 customer_id 插入一个空值

不同的方法(由@wildplasser 提出)

INSERT INTO contacts(customer_id, contact_name ) 
select customer_id,'thomas' from customers where customer_name = 'my_first_customer';

在这种情况下,如果没有指定名称的客户,则不会创建任何行。当有多个客户具有给定名称时,将为每个客户创建记录。

或者您可以使用 INSTEAD OF 触发器创建视图。

create view v_contacts as 
select customer_name, contact_name from customers 
  join contacts on customers.customer_id = contacts.customer_id;
CREATE FUNCTION emp () RETURNS trigger AS $$
BEGIN
    
  INSERT INTO contacts(customer_id, contact_name ) 
    VALUES((select customer_id from customers where customer_name = 
       NEW.customer_NAME),NEW.contact_NAME);
    
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER v_contactst
    INSTEAD OF INSERT ON v_contacts
    FOR EACH ROW
EXECUTE FUNCTION emp();    

插入语句

INSERT INTO v_contacts(customer_name, contact_name ) VALUES('my_first_customer','thomas')

请注意,customer_namecontact_name 列不是唯一的,因此此代码不安全,如果 customer_name 不存在或超过一条记录 customer_name