Ссылка на стандартный параметр, когда в области видимости находятся столбцы таблицы с таким же именем - PullRequest
0 голосов
/ 14 мая 2019

Допустим, у меня есть таблица с именем "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

Конечно, я мог бы дать рутинный параметр aдругое, отличное имя, но я бы посчитал, что это скорее обходной путь, чем решение, потому что тогда функциональность подпрограммы будет зависеть от таблицы «Люди», не содержащей столбца с именем, идентичным имени параметра подпрограммы, котороечто-то, что может измениться без рутины, зная об этом.

Итак, я делаю / понимаю что-то здесь не так, или я действительно вынужден прибегнуть к грубым обходным путям, чтобы решить эту дилемму?

Ответы [ 2 ]

0 голосов
/ 15 мая 2019

Узнав из ответа Фредта о невозможности определения имени параметра, я пришел к не очень элегантной конструкции, которая, тем не менее, решает проблему, которую я рассмотрел в этом вопросе.Вместо того, чтобы заполнять таблицу возврата, выбирая непосредственно из таблицы "People", в которой может быть любое количество столбцов с произвольными именами, о которых процедура не знает, я создаю подзапрос, действующий как «конвейер» для таблицы "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 всегда будет ссылаться на параметр рутины, даже если по какой-то непостижимой причине кто-то добавляет столбец с именем "FirstName_Param" к таблице "People", поскольку таблица "People" находится вне области действия в предложении WHERE.

0 голосов
/ 14 мая 2019

Вам нужно использовать разные имена для переменных.Пользователи обычно используют соглашение об именах для параметров, показанное в этом примере из руководства 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 не позволяет переименовывать столбец таблицы, который используется в подпрограмметак что это не может пойти не так с последующими изменениями.

...