Firebird/Lazarus SQL 视图与选择 iif?
Posted
技术标签:
【中文标题】Firebird/Lazarus SQL 视图与选择 iif?【英文标题】:Firebird/Lazarus SQL View with select iif? 【发布时间】:2019-02-15 12:16:39 【问题描述】:我想从一个表中选择行,该表的计算字段由选择查询定义。
例如,我的选择可能是:
Select FirstName,
LastName,
iif(Cast('Now' as date)-BirthDate<18, 'Minor', 'Major') as StatAge
from TableUsers;
对于 Lazarus,我想过滤 StatAge。
我使用工具直接在我的数据库上尝试了我的查询。
我可以像这样在查询中使用 Where 进行过滤:
Select *
from (
Select FirstName,
LastName,
iif(Cast('Now' as date)-BirthDate<18, 'Minor', 'Major') as StatAge
from TableUsers
)
Where StatAge = 'Minor';
但它不适用于 TSQLQuery.Filter
的 lazarus 我可以过滤其他字段,没问题。我的问题只在于这个计算字段。
所以也许我必须在我的数据库上创建一个视图?但是当我尝试使用查询添加视图时出现错误。
创建视图的我的SQL代码如下,错误是
“元数据更新失败无法格式化消息 8:132 -- 找不到消息文件 C:\WINDOWS\SYSTEM32\firebird.msg。
我以前从未见过:
CREATE VIEW "TSTT_SELECT" ("ID_SENT", "Eng", "Char", "ID_STT", "Order", "Stat", "StartSAE", "RetSAE", "ArrSAE", "StartSHE", "RetSAE")
AS
Select "EMAIL_SENT"."ID", "EMAIL_SENT"."COMMANDE_TABLE", "EMAIL_SENT"."CHAR", "TSTT"."ID", "TSTT"."ORDER", iif("TSTT"."RETOUR_PREV" Is Not Null AND ("TSTT"."RETOUR_PREV">cast('Now' as date)), 'En retard', iif("TSTT"."Depart_SAE" Is Null, 'A expedier', iif("TSTT"."Depart_SAE" Is Not Null And "TSTT"."Arrivee_SHE" Is Not Null And "TSTT"."Depart_SHE" is null,'Chez le STT',iif("TSTT"."Depart_SHE" Is Not Null, 'Au depart STT', iif("TSTT"."Arrivee_SAE" Is Not Null, 'Récéptionné', ''))))) as "Statut", "TSTT"."Depart_SAE", "TSTT"."RETOUR_PREV", "TSTT"."Arrivee_SHE", "TSTT"."Depart_SHE", "TSTT"."Arrivee_SAE"
from "EMAIL_SENT"
Left join "TSTT" on "EMAIL_SENT"."ID" = "TSTT"."ID_EMAIL";
【问题讨论】:
你在这里混合了两个不同的问题:在 FPC/Lazarus 中使用TSQLQuery.Filter
和在 Firebird 中创建视图。这些是不同的问题和不同的程序。 W.r.t. Firebird - 您似乎没有在系统上安装 Firebird 客户端。所以fbclient.dll
附近没有firebird.msg
文件 - 因此它无法为您提供错误文本。找到最新的 Firebird 版本的 msg 文件并将其放在您的程序使用的客户端 dll 附近。附言也最好使用CURRENT_DATE
var, firebirdsql.org/refdocs/langrefupd25-now.html
错误似乎是代码 336068740,即 Table ... 已经存在。这表明您已经有一个名为 TSTT_SELECT
的视图(或表)。
@MarkRotteveel 你怎么知道代码的?为 8:132 抓取 FB 资源?
@Arioch'错误代码是0x14000000 | (facility << 16) | (number & 0xFFFF)
,这里的设备是8,数字是132。虽然我也可以在8, 132
上搜索src/msgs/message2.sql
。
【参考方案1】:
假设您的 BirthDate
字段的类型为 Date
,如果您使用像 FlameRobin 这样的实用程序首先执行
你在 q 中引用的 SQL,然后是下面的 SQL,你会看到你的 SQL 中有一个错误。错误是您的 iff
返回了 days 的数量,而不是 years
所以iff
的返回值是错误的。我不是很熟悉
使用 Firebird SQL,所以在我的版本中通过相乘“修复”了这个问题
18 x 365 当然忽略闰年。
Select FirstName,
LastName,
Birthdate,
iif(Cast('Now' as date)-BirthDate<18 * 365, 'Minor', 'Major') as StatAge ,
Cast('Now' as date)-BirthDate
from TableUsers;
然后我设置了下面列出的最小 Lazarus 项目,它工作正常, 包括正确过滤 edFilter.Text 表达式。
代码:
TForm1 = class(TForm)
Button1: TButton;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
edFilter: TEdit;
SQLConnector1: TSQLConnector;
SQLQuery1: TSQLQuery;
SQLTransaction1: TSQLTransaction;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
public
end;
[...]
procedure TForm1.Button1Click(Sender: TObject);
begin
if not SQLQuery1.Filtered then
SQLQuery1.Filter := edFilter.Text
else
SQLQuery1.Filter := '';
SQLQuery1.Filtered := not SQLQuery1.Filtered;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
edFilter.Text := 'STATAGE = ''Minor''';
SQLQuery1.Sql.Text :=
'Select '#13#10
+ ' FirstName, '#13#10
+ ' LastName, '#13#10
+ ' Birthdate, '#13#10
+ ' iif(Cast(''Now'' as date)-BirthDate<18 * 365, ''Minor'', ''Major'') as StatAge , '#13#10
+ ' Cast(''Now'' as date)-BirthDate '#13#10
+ 'from TableUsers2;';
SqlQuery1.Open;
end;
【讨论】:
这对您的过滤问题有帮助吗?【参考方案2】:所以, 我用 IBX4Lazarus 组件解决了我的问题。这是 Interbase/firebird 的特定组件。
我过去使用它是因为 firebird 没有被 lazarus 集成。现在,我们可以使用标准的 lazarus 组件连接到 firebird DB,但是我们可以看到存在一些问题......所以我将只使用 IBX 组件进行更好的优化。
使用 IBX4Lazarus 解决了我的问题:www.mwasoftware.co.uk
【讨论】:
嗯。我不确定我是否相信您的问题已“解决”。我在您的 Q 中发现了一个错误,这意味着如果我的假设是正确的,它可能无法正常工作。我有一个用 Delphi 编写的最小项目,它工作正常(包括过滤)。我会尝试为 Lazarus 重写它,并在接下来的一个小时左右将它作为新答案发布,假设它有效。以上是关于Firebird/Lazarus SQL 视图与选择 iif?的主要内容,如果未能解决你的问题,请参考以下文章