PostgreSQL 零或一到零或一的关系

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

正如标题所描述的,我想要建立一种零或一到零或一的关系。
例如,假设我们有两个表CallsFiles。呼叫可能带有附加文件,反之亦然。但我有一个限制。我希望如果我删除一个呼叫,它的文件也会被删除,但是如果我删除它的文件呼叫应该保持原样。使用SQL Constraints(如

ON DELETE CASCADE
/
ON DELETE SET NULL
)可以实现这样的事情吗?或者有什么办法,用 SQL 在数据库中实现这样的行为,而不使用触发器/事件?

我尝试了如下所示:

-- Create the 'files' table
CREATE TABLE files (
    id SERIAL PRIMARY KEY,  -- Primary key for the 'files' table
    file_name TEXT NOT NULL -- Any additional fields for the 'files' table
);

-- Create the 'calls' table
CREATE TABLE calls (
    id SERIAL PRIMARY KEY,  -- Primary key for the 'calls' table
    file_id INT UNIQUE,     -- Foreign key referencing 'files' table (1-1 relationship)
    call_description TEXT,  -- Any additional fields for the 'calls' table
    CONSTRAINT fk_file_id FOREIGN KEY (file_id) REFERENCES files(id) ON DELETE SET NULL
);

-- Add an additional constraint on the 'files' table to enforce the cascading behavior
ALTER TABLE files
ADD CONSTRAINT fk_call_file
FOREIGN KEY (id)
REFERENCES calls(file_id)
ON DELETE CASCADE;

但它需要可推迟,因为约束是立即执行的。而且,这也不是我的本意。我希望存在一个调用/文件而不相互依赖。

在这种情况下应遵循哪些最佳实践?

sql database postgresql foreign-keys relationship
1个回答
0
投票

我可以想到多种方法来做到这一点:

  1. 如果有意义,则反转关系,以便文件引用调用。
  2. 使用触发器
  3. 只需删除
    file
    而不是
    call
    ,文件就会级联到调用:
delete from files where id = (select file_id from calls where id = :call)
  1. 如果您根本不需要任何级联,您可以使用 CTE(公共表表达式)编写多个语句:
with deleted_calls as (
  delete from calls where id = :call
  returning (file_id)
)
delete from files where id = (select file_id from deleted_calls);

请注意,

calls
表有 2 个查询。如果我们没有 FK,我们可以先删除

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