在 Firebird 中创建一个显示来自另一个 table 的数据的字段

Create a field in Firebird which displays data from another table

我没有找到在 Firebird 数据库中创建 "lookup column" 的有效解决方案。

这是一个例子:

Table1:订单 [订单 ID] [客户 ID] [客户名称]

Table2:客户 [ID] [姓名]

当我 运行 SELECT * FROM ORDERS 我想获取 OrderID、CustomerID 和 CustomerName....但是 CustomerName 应该通过在 [=24] 中查找 "CustomerID" 来自动计算=] "Customer" Table 列,返回 "Name" 列的内容。

Firebird 有 calculated fields (generated always as/computed by),这些允许从其他 tables 中选择(与早期版本相反这个答案,它声明 Firebird 不支持这个 ).

但是,我建议您改用视图,因为我认为它的性能更好(尚未验证这一点,所以如果性能很重要,我建议您测试一下)。

使用视图

通常的方法是定义一个基 table 和一个随附的 view,用于在查询时收集必要的数据。人们会从视图中查询而不是使用基础 table。

create view order_with_customer
as
select orders.id, orders.customer_id, customer.name
from orders
inner join customer on customer.id = orders.customer_id;

或者您可以跳过视图并在您自己的查询中使用上面的连接。

备选方案:计算字段

我将其标记为替代方案而不是主要解决方案,因为我认为使用视图是更好的解决方案。

要使用计算字段,您可以使用以下语法(注意查询两边的双括号):

create table orders (
    id integer generated by default as identity primary key,
    customer_id integer not null references customer(id),
    customer_name generated always as ((select name from customer where id = customer_id))
)

customer table 的更新将自动反映在 orders table 中。

据我所知,此选项的性能低于使用连接时的性能(如视图示例中所用),但您可能想自己测试一下。

具有功能

的FB3+

使用 Firebird 3,您还可以使用触发器创建计算字段,这会使表达式本身更短。

为此,创建一个 function 从客户 table 中选择:

create function lookup_customer_name(customer_id integer) 
    returns varchar(50)
as
begin
    return (select name from customer where id = :customer_id);
end

然后创建 table 为:

create table orders (
    id integer generated by default as identity primary key,
    customer_id integer not null references customer(id),
    customer_name generated always as (lookup_customer_name(customer_id))
);

customer table 的更新将自动反映在 orders table 中。选择大量记录时,此解决方案的速度可能相对较慢,因为该函数将分别为每行执行,这比执行JOIN的效率要少得多。

备选方案:使用触发器

但是,如果您想在插入(或更新)时使用来自另一个 table 的信息更新 table,您可以使用 trigger.

我将使用 Firebird 3 作为我的答案,但它应该也可以转换为较早的版本(但有一些细微差别)。

所以假设 table customer:

create table customer (
    id integer generated by default as identity primary key,
    name varchar(50) not null
);

样本数据:

insert into customer(name) values ('name1');
insert into customer(name) values ('name2');

还有一个table orders:

create table orders (
    id integer generated by default as identity primary key,
    customer_id integer not null references customer(id),
    customer_name varchar(50) not null
)

然后定义触发器:

create trigger orders_bi_bu 
    active before insert or update
    on orders
as
begin
    new.customer_name = (select name from customer where id = new.customer_id);
end

现在当我们使用:

insert into orders(customer_id) values (1);

结果是:

id  customer_id  customer_name
1   1            name1

更新:

update orders set customer_id = 2 where id = 1;

结果:

id  customer_id  customer_name
1   2            name2

触发器的缺点是更新 customer table 中的名称不会自动反映在 orders table 中。您需要自己跟踪这些依赖关系,并在 customer 上创建一个更新后触发器来更新依赖记录,这可能会导致 update/lock 冲突。

这里不需要复杂的查找字段。 无需在表 1 上添加持久字段 [CustomerName]。

正如 Gordon 所说,一个简单的 Join 就足够了:

Select T1.OrderID,  T2.ID,  T2.Name
From Customers T2 
Join Orders T1 On T1.IDOrder = T2.ID

就是说,如果您想将查找字段(就像我们在数据集上所做的那样)与 SQL 一起使用,您可以使用类似的东西:

Select T1.OrderID,  T2.ID,  
( Select T3.YourLookupField From T3 where (T3.ID = T2.ID)  )
From Customers T2 Join Orders T1 On T1.IDOrder = T2.ID

此致。