您还可以选择使用 reversedLIKE
而不是IN
. 毕竟,IN
随着项目数量的增加,在 Interbase/Firebird 上可能会变慢。LIKE
总是会对整个表进行自然扫描。如果项目数量很少,则速度会慢得多,但不会随着项目数量的增加而减慢。
进行自己的分析。您甚至可以根据参数字符串长度切换到一种或另一种策略。您对 32KB 的 FirebirdVarChar
长度限制感到困惑,也许这对您的应用程序很重要。
因此,对于一般方向,请参阅我在https://stackoverflow.com/a/43997801/976391的回答
将“Route #2”应用于您的案例将是这样的......
ALTER PROCEDURE SP_STOCK_ANALYSIS
(
MAIN_GROUP varCHAR(32760) character set ascii
)
RETURNS
(
STOCK_CODE varCHAR(21),
STOCK_GROUP varCHAR(6),
DESCRIPTION varCHAR(31),
EXPENSE NUMERIC(15, 4)
)
AS
BEGIN
FOR
SELECT
L.STOCK_CODE, INV.DESCRIPTION, INV.STOCK_GROUP, L.BALANCE
FROM
LEDGER L LEFT JOIN INVENTORY INV ON L.STOCK_CODE = INV.STOCK_CODE
WHERE
(:MAIN_GROUP CONTAINING '~' || INV.STOCK_GROUP || '~')
-- INV.STOCK_GROUP in (:MAIN_GROUP)
AND (L.LEDGER_ACCOUNT in ('71212', '71211' ,'83791'))
INTO
STOCK_CODE, STOCK_GROUP, DESCRIPTION, EXPENSE
DO
.....
然后你这样打电话:
SELECT * FROM SP_STOCK_ANALYSIS ('~1~4~8~11~')
LIST
您可以使用聚合函数将返回 ID 的查询转换为字符串,例如
SELECT '~' || LIST (ID, '~') || '~' FROM source-table WHERE ........
但我认为在工程方面,最好使用事务本地GTT
(全局临时表)而不是双重转换,然后join
在你的 SP 中自然地做。
insert into SP-helping-GTT
SELECT ID FROM source-table WHERE ........;
...然后执行无参数 SP,然后只是COMMIT
清理GTT
当然,缺点是隐含的严格耦合和命名空间污染。
但是由于您一次对两个表进行多次过滤 -L
并且INV
- 并且您可能希望将两个列表都转换为参数,因此joining
对于关系数据库引擎来说,两个表 (GTT) 将是自然的,而两个嵌套的自然扫描将变得很差 O(n ^2) 缩放。
此外,您真的会考虑是否需要外来CHAR
数据类型而不是VARCHAR
. 这确实是一个小麻烦,但人们不知何故一次又一次地被它绊倒。
……这些只是少数。