我没有找到一个有效的解决方案来创建一个"查询列"在Firebird数据库中。
以下是一个例子:
表1:订单 [OrderID] [CustomerID] [客户名称]
表2:客户 [ID] [姓名]
当我运行SELECT * FROM ORDERS
时,我想获得OrderID,CustomerID和CustomerName ....但是CustomerName应该通过查找" CustomerID"来自动计算。在" ID" "客户"表,返回"名称"的内容列。
答案 0 :(得分:2)
Firebird有calculated fields(generated 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
表中。
据我所知,此选项的性能低于使用连接时的性能(在视图示例中使用),但您可能希望自己测试一下。
使用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
致谢。