如何在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_name
和 contact_name
列不是唯一的,因此此代码不安全,如果 customer_name
不存在或超过一条记录 customer_name
我目前在 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_name
和 contact_name
列不是唯一的,因此此代码不安全,如果 customer_name
不存在或超过一条记录 customer_name