在Firebird中创建一个字段,显示另一个表中的数据

时间:2017-11-03 21:51:21

标签: sql firebird

我没有找到一个有效的解决方案来创建一个"查询列"在Firebird数据库中。

以下是一个例子:

表1:订单 [OrderID] [CustomerID] [客户名称]

表2:客户 [ID] [姓名]

当我运行SELECT * FROM ORDERS时,我想获得OrderID,CustomerID和CustomerName ....但是CustomerName应该通过查找" CustomerID"来自动计算。在" ID" "客户"表,返回"名称"的内容列。

2 个答案:

答案 0 :(得分:2)

Firebird有calculated fieldsgenerated always as / computed by),这些允许从其他表中进行选择(与此答案的早期版本相反,后者表示Firebird没有&# 39; t支持)。

但是,我建议您使用视图,因为我认为它的效果更好(尚未对此进行验证,因此如果性能很重要,建议您对此进行测试)。

使用视图

常见的方法是定义一个基表和一个伴随的view,它在查询时收集必要的数据。人们不会使用基表,而是从视图中进行查询。

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表的更新将自动反映在orders表中。

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

FB3 +功能

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

为此,请创建一个从客户表中选择的function

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

然后将表格创建为:

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表的更新将自动反映在orders表中。选择大量记录时,此解决方案可能相对较慢,因为该功能将单独为每一行执行,这比执行连接效率低得多。

替代方案:使用触发器

但是,如果您想在插入(或更新)时使用其他表中的信息更新表,则可以使用trigger

我将使用Firebird 3作为我的答案,但它应该与早期版本一起翻译 - 虽然有一些细微差别。

假设有一个表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');

表格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表中的名称不会自动反映在orders表中。您需要自己跟踪这些依赖关系,并在customer上创建更新依赖记录的更新后触发器,这会导致更新/锁定冲突。

答案 1 :(得分:0)

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

正如戈登所说,简单的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

致谢。