firebird - 在 Firebird SQL 中使用循环
问题描述
我希望我的 Firebird SQL 在满足条件时循环遍历部分代码。
一开始我什至不认为这是可能的。但是我已经阅读了一些内容,现在相信我可以使用 WHILE 循环。
我知道 FOR 循环不是我想要的,因为它适用于整个代码,而不仅仅是它的一部分。
我在 Excel 中使用它,并且可以使用一些 VBA 代码来做我想做的事,但如果我可以通过 Firebird SQL 完成这一切会更好,因为我可以在其他地方应用它。
SELECT
'1' as "Qty",
'of ' || ALP3.PROPERTYVALUE AS "Total Qty"
FROM ASSEMBLYLINES
LEFT JOIN ASSEMBLYLINEPROPS ALP1 ON ALP1.HEADERSYSUNIQUEID = ASSEMBLYLINES.SYSUNIQUEID AND ALP1.PROPERTYNAME = 'Process2'
LEFT JOIN ASSEMBLYLINEPROPS ALP2 ON ALP2.HEADERSYSUNIQUEID = ASSEMBLYLINES.SYSUNIQUEID AND ALP2.PROPERTYNAME = 'Process3'
LEFT JOIN ASSEMBLYLINEPROPS ALP3 ON ALP3.HEADERSYSUNIQUEID = ASSEMBLYLINES.SYSUNIQUEID AND ALP3.PROPERTYNAME = 'Job Quantity'
LEFT JOIN ASSEMBLYLINEPROPS ALP4 ON ALP4.HEADERSYSUNIQUEID = ASSEMBLYLINES.SYSUNIQUEID AND ALP4.PROPERTYNAME = 'Drawing No'
WHERE ASSEMBLYLINES.ORDERNUMBER='16708R01'
AND ASSEMBLYLINES.LINECODE='FABPART'
AND ASSEMBLYLINES.SYSUSERCREATED <> 'EXTERNAL USER'
ORDER BY ALP4.PROPERTYVALUE
我使用上面代码的结果是:
数量 总数量 1 4
但是,我想要的是:
我使用上面代码的结果是:
数量 总数量 1 4 2 4 3 4 4 4
我了解 While 循环将类似于:
While Qty <= ALP3.PROPERTYVALUE Do
<<output>>
Loop
解决方案
Qty Total Qty
1 4
2 4
3 4
4 4
I understand the While loop would be something like:
While Qty <= ALP3.PROPERTYVALUE Do
<<output>>
Loop
因此,您的“数量”列实际上不是一些真实数据的数量(如货船中的集装箱数量),而是一些输出报告/网格中的行号。然后你想要的是将输出“行集” - 矩阵、表格、网格 - 限制为前 N 行。
好吧,这正是它的完成方式,只要求第一行。
Select FIRST(4) column1, column2, column3
From table 1
Where condition1 and condition2 or condition3
请参阅文档中的“第一个”子句:https ://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-dml-select.html
另请参阅维基百科中的“限制结果行”章节:https ://en.wikipedia.org/wiki/Select_%28SQL%29#Limiting_result_rows
您也可以从 Firebird 版本 3 开始使用“窗口函数”,但对于“只给我前 N 行”这样的简单任务来说,它们有点过分了。
现在,还有另一种方法可以嵌入完全自愿的条件,但这来自“丑陋的黑客”工具集,并且在运行来自不同客户端程序的多个同时连接的典型情况下不起作用。您可以使用“生成器”作为 WHILE 子句的一部分:
Select .....
Where (GEN_ID(cancel_generator_name, 0) = 0) AND ( ...you normal conditions...)
您在查询之前将生成器值设置为 0,并且您的客户端在读取数据时评估您选择的一些条件,并且当它想要时 - 从另一个 SQL 命令库对象发出生成器更改命令,该命令将立即跳过其余的查询。然而,虽然有时这是一种有用的技术,但仅限于非常特殊的罕见情况。
既然马克似乎比我更善于猜测,那么就为未来的猜测做一些概述。
SP 是 SQL 存储过程的标准缩写。FirebirdExecute Block
本质上是一个匿名的非持久性 SP。
因此,我们从一个持久且命名的 SP 开始。
create or alter procedure SEQ (
FROM_1_TO integer not null)
returns (
COUNTER integer)
as
begin
counter = 1;
while ( counter <= from_1_to ) do begin
suspend;
counter = counter + 1;
end
end
Select 1, s.counter from rdb$database, seq(5) s
CONSTANT COUNTER
1 1
1 2
1 3
1 4
1 5
下一个问题是如何
- 根据特定表行值将表与 SP(存储过程)联接
- 避免使用 NULL 参数值执行 SP
答案是 - LEFT JOIN
,如常见问题解答中所示:http ://www.firebirdfaq.org/faq143/
CREATE TABLE T2 (
ID INTEGER NOT NULL PRIMARY KEY,
TITLE VARCHAR(10) NOT NULL,
QTY INTEGER NOT NULL
);
INSERT INTO T2 (ID, TITLE, QTY) VALUES (1, 'aaaa', 2);
INSERT INTO T2 (ID, TITLE, QTY) VALUES (2, 'bbbb', 5);
INSERT INTO T2 (ID, TITLE, QTY) VALUES (3, 'ccccc', 4);
Select * from t2 t
left join seq(t.qty) s on 1=1
ID TITLE QTY COUNTER
1 aaaa 2 1
1 aaaa 2 2
2 bbbb 5 1
2 bbbb 5 2
2 bbbb 5 3
2 bbbb 5 4
2 bbbb 5 5
3 ccccc 4 1
3 ccccc 4 2
3 ccccc 4 3
3 ccccc 4 4
如果您对需要添加此行克隆的不同表/字段有许多不同的查询,那么拥有一个专用的反生成 SP 是有意义的。
但是,如果您只需要克隆一次这种相当奇特的行,那么使用您再也不需要的 SP 污染全局命名空间可能不是一个好主意。
不过,似乎无法从 EB 中进行选择:从执行块中选择?
select
因此,您必须为您的声明制作一个特定的临时 EB 。可以说,这可能是匿名非持久性 EB 存在的原因。
execute block
returns (ID INTEGER, TITLE VARCHAR(10), QTY INTEGER, COUNTER INTEGER)
as
begin
for select
id, title, qty from t2
into :id, :title, :qty
do begin
counter = 1;
while
(counter <= qty)
do begin
suspend;
counter = counter + 1;
end
end
end
但是,您的应用程序用来连接到 Firebird 的数据访问库应该明白,虽然这个查询不是 SELECT 查询,但它仍然返回“行集”。通常他们会这样做,但谁知道呢。
推荐阅读
- node.js - Node.js express,请求 jwt 令牌 - 如果请求中过期,如何正确获取新的有效令牌
- python - 如何在 matplotlib 中添加标记样式列表?
- android - 如何安全地共享 apk 文件而不是在邮件中共享?
- apache - .htaccess mod_rewrite 编码的 URL 路径不工作,而未编码的路径工作
- angular - 将外部组件作为 Angular2+ 中的属性传递
- css - 未使用 nginx 在不同子域从 CSS 加载的图像
- java - JPA 查询元素集合
- apache-flink - 为 Flink DataStream 执行选择节点
- swift - 默认情况下,如何阻止 Xcode 倒置启动模拟器并启动景观?
- reactjs - ReactJS _ 文本编辑器 - 现有的 ReactJS 文本编辑器与 libreoffice 编辑器一样完整?