假设我有一个名为"People"
的表,该表有两列"FirstName"
和"LastName"
,下面的函数引用了该表(这是一个人为设计和简化的示例,其唯一目的是说明我的问题):
CREATE FUNCTION PUBLIC."SelectPeopleByFirstName" (
IN "FirstName" VARCHAR(100)
)
RETURNS TABLE (
"FirstName" VARCHAR(100)
, "LastName" VARCHAR(100)
)
READS SQL DATA
RETURN TABLE (
SELECT
"People"."FirstName"
, "People"."LastName"
FROM
PUBLIC."People"
WHERE
"People"."FirstName" = "FirstName"
)
问题在于,在WHERE
语句的SELECT
子句中,标识符"FirstName"
被视为对表列"People"."FirstName"
的引用,而不是例程参数"FirstName"
。
现在,Google告诉我,我不是第一个遇到此问题的人,从我可以找到的各种建议的解决方案中,我发现最满意的是使用常规名称来限定标识符,例如: :
WHERE
"People"."FirstName" = "SelectPeopleByFirstName"."FirstName"
不幸的是,这似乎不适用于HSQLDB,因为出现了以下错误:
用户缺少特权或找不到对象:SelectPeopleByFirstName.FirstName /错误代码:-5501 /状态:42501
当然,我可以给例程参数一个不同的名称,但是我认为这更多的是解决方法,而不是解决方案,因为这样例程的功能将取决于表“ People”中不包含列的名称与例程参数的名称相同,这可能会在例程不知道的情况下更改。
那么我是在这里做/理解错了吗,还是真的为了解决这个难题而不得不采取粗略的解决方法吗?
答案 0 :(得分:0)
您需要对变量使用不同的名称。用户通常对参数使用命名约定,如《 HSQLDB指南》中的本示例所示,并在名称后附加_P
。
CREATE PROCEDURE test_proc(INOUT val_p INT, IN lastname_p VARCHAR(20))
MODIFIES SQL DATA
BEGIN ATOMIC
SET val_p = 0;
for_label: FOR SELECT * FROM customer WHERE lastname = lastname_p DO
IF val_p > 0 THEN
DELETE FROM customer WHERE customer.id = id;
END IF;
SET val_p = val_p + 1;
END FOR for_label;
END
HSQLDB不允许您重命名例程中使用的表列,因此以后的更改不会出错。
答案 1 :(得分:0)
从fredt的答案得知不可能限定参数名称后,我想到了一个并非十分优雅的构造,但仍解决了我在问题中解决的问题。我没有直接从"People"
表中进行选择来填充返回表,该表可以具有例程不知道的任意数量的具有任意名称的列,我创建了一个子查询,充当了{{1 }}表并从此子查询中选择:
"People"
现在,CREATE FUNCTION PUBLIC."SelectPeopleByFirstName" (
IN "FirstName_Param" VARCHAR(100)
)
RETURNS TABLE (
"FirstName" VARCHAR(100)
, "LastName" VARCHAR(100)
)
READS SQL DATA
RETURN TABLE (
SELECT
"FirstName"
, "LastName"
FROM (
SELECT
"FirstName"
, "LastName"
FROM
PUBLIC."People"
)
WHERE
"FirstName" = "FirstName_Param"
)
子句中的标识符"FirstName_Param"
将始终引用例程参数,即使出于某些不可思议的原因,有人将WHERE
列添加到表{ {1}},因为表"FirstName_Param"
在"People"
子句中超出范围。