在 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
此致。
我没有找到在 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
此致。