我认为没有办法做你想做的事;我确信没有一种简单的方法可以做类似的事情。
设置
考虑一个包含两个表的数据库:一个(化学)元素表 - 元素周期表 - 和一个(美国)州表。
CREATE TABLE elements
(
atomic_number INTEGER NOT NULL PRIMARY KEY
CHECK (atomic_number > 0 AND atomic_number < 120),
symbol CHAR(3) NOT NULL UNIQUE,
name CHAR(20) NOT NULL UNIQUE,
atomic_weight DECIMAL(8, 4) NOT NULL,
pt_period SMALLINT NOT NULL
CHECK (pt_period BETWEEN 1 AND 7),
pt_group CHAR(2) NOT NULL
-- 'L' for Lanthanoids, 'A' for Actinoids
CHECK (pt_group IN ('1', '2', 'L', 'A', '3', '4', '5', '6',
'7', '8', '9', '10', '11', '12', '13',
'14', '15', '16', '17', '18')),
stable CHAR(1) DEFAULT 'Y' NOT NULL
CHECK (stable IN ('Y', 'N'))
);
CREATE TABLE US_States
(
code CHAR(2) NOT NULL PRIMARY KEY,
name VARCHAR(15) NOT NULL UNIQUE
);
我假设您可以使用正确的数据填充这两个表(请参阅 Web Elements 以了解元素周期表;Informix 演示数据库“商店”有一个表 state 与此处使用的 US_States 表同构) .
现在考虑一个过程states_starting():
CREATE FUNCTION states_starting(initial CHAR(1)) RETURNING VARCHAR(15);
DEFINE result VARCHAR(15);
FOREACH SELECT Name
INTO result
FROM US_States
WHERE Code[1] = initial
ORDER BY Name
RETURN result WITH RESUME;
END FOREACH;
END FUNCTION;
调整问题中的查询
我有点惊讶vt(result) 表示法有效——但它确实有效,指定了一个表别名vt 和列名result。因此,有效的查询的改编是:
SELECT *
FROM Elements, TABLE(states_starting('M')) vt(result)
这会生成 118 个元素和 8 个状态的笛卡尔积,名称以“M”开头,共 944 行。一个稍微合理的查询是:
SELECT *
FROM Elements JOIN TABLE(states_starting('M')) AS vt(result)
ON Elements.Symbol[1] = vt.result[1]
ORDER BY Elements.Atomic_Number
这会生成 6 种元素的结果(镁、
锰,
迈特里姆,
钔,
钼,
Moscovium:水星没有出现,因为它的符号是 Hg,它不以 M 开头)和以前的 8 个状态,共 48 行。
您要执行的查询的适配如下所示:
SELECT *
FROM Elements AS e
JOIN TABLE(states_starting(e.name[1])) AS vt(result)
ON Elements.Symbol[1] = vt.result[1]
ORDER BY Elements.Atomic_Number
这不起作用,但是会产生错误:
-217: Column (name) not found in any table in the query (or SLV is undefined).
这与问题中的错误不同;我无法复制它。但这是该查询面临的问题的症状。
问题是在TABLE(…) 中,名称e 是未知的,但从参数中删除e. 并不会改变事情。
此外,要生成完整的“正确”结果,TABLE(…) 表达式必须被计算多次,每个单独的首字母计算一次。因此,您需要在 TABLE(…) 表达式中使用不同参数多次调用该函数的一组表结果。但这不是表在 SQL 中的工作方式。它们应该是“固定的”。函数的常量参数产生一个结果集,看起来像一个表。但是尝试使用不同的参数多次调用它并处理结果集(充其量)会很棘手——这不是 SQL 的工作方式。
我对这个解释并不完全满意。我试图表达的想法几乎可以肯定是查询不起作用的原因,但我不高兴我解释得很好。
我尝试了多种变体。例如,假设您创建了一个GROUP_CONCAT aggregate,您可能想尝试:
SELECT group_concat(states_starting(a))
FROM (SELECT DISTINCT NAME[1] AS a FROM us_states)
GROUP BY a
但这会产生:
-686: Function (states_starting) has returned more than one row.
我认为从函数结果创建 SET 或 LIST 没有帮助。
在 Mac OS X 10.11.5 和 Informix 12.10.FC6(以及 ClientSDK 4.10.FC6 和 SQLCMD 90.01 — 与 Microsoft 的同名 johnny-come-lately 无关)上进行测试。