当作用域中的表列名称相同时,引用例程参数

时间:2019-05-13 21:37:11

标签: hsqldb

假设我有一个名为"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”中不包含列的名称与例程参数的名称相同,这可能会在例程不知道的情况下更改。

那么我是在这里做/理解错了吗,还是真的为了解决这个难题而不得不采取粗略的解决方法吗?

2 个答案:

答案 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"子句中超出范围。