Хранимая процедура не может быть вызвана из-за синтаксической ошибки - PullRequest
1 голос
/ 06 января 2020

Мы мигрировали с SQL Сервера на Postgres, и я пытаюсь переписать хранимую процедуру. Процедура создана правильно, но я не могу ее вызвать.

Это моя процедура:

CREATE OR REPLACE PROCEDURE spr_getItems  ( 
  p_kind int = NULL,
  p_customerId varchar(256) = NULL,
  p_resourceIds varchar(2048) = NULL,
  p_referenceIds varchar(2048) = NULL
)
AS $$
BEGIN
  SELECT
    c.kind,
    c.name AS customerName,
    c.oid AS customerId,
    r.name AS resourceName,
    r.oid AS resourceId
    o.fullObject AS fullObjectString
  FROM m_customer c
  JOIN m_resource r
    ON r.oid = c.resourceOid
  LEFT JOIN m_object o
    ON o.customerOid = c.oid
      AND o.customerOid = p_customerId
  WHERE (c.kind = p_kind OR p_kind is NULL)
    AND (c.referenceOid IN (SELECT refTemp.oid FROM tvf_commaSeperatedStringToTable(p_referenceIds) refTemp) OR p_referenceIds is NULL)
    AND (r.oid IN (SELECT resTemp.oid FROM tvf_commaSeperatedStringToTable(p_resourceIds) resTemp) OR p_resourceIds is NULL); 
END;
$$

LANGUAGE 'plpgsql';

табличная функция tvf_commaSeperatedStringToTable просто берет строку, разбивает ее и возвращает таблицу со всеми различными идентификаторами и номером. Он работает просто отлично и протестирован, здесь нет ошибок.

Теперь, когда я пытаюсь выполнить его следующим образом

CALL public.spr_getItems (0, null, null, null)

, я получаю следующий вывод:

ОШИБКА: у запроса нет места назначения для данных результата

СОВЕТ: Если вы хотите отменить результаты SELECT, используйте вместо этого PERFORM.
КОНТЕКСТ: PL / pg SQL функция spr_getItems (целое число, символ изменяющийся, изменяющийся символ, изменяющийся символ) строка 3 в SQL оператор
SQL состояние: 42601

Но я НЕ хочу отменить результат, я хочу их увидеть.

Итак, я попытался вызвать его с помощью select

SELECT * 
FROM CALL spr_getItems (0, null, null, null)

, и затем я получил эту синтаксическую ошибку:

ERROR: синтаксическая ошибка в или около "0"
LINE 2: 0,
^
SQL состояние: 42601
Символ: 40

Я также попытался выполнить его несколькими другими способами, например, добавив «publi *» 1055 * «. перед именем процедуры, но затем произошла синтаксическая ошибка в «.». Или просто с помощью select spr_getItems(0, null, null, null) или select spr_getItems(0), select * from call spr_getItems (0) и т. Д. И т. П.

Я делаю что-то совершенно неправильно и что-то упустил из виду в документации?

Спасибо за любые help!

Edit: уточнение, что я хочу увидеть результаты
Edit2: случайно скопировал неправильное имя функции
Edit3: добавлено полное тело в соответствии с предложением

Ответы [ 3 ]

1 голос
/ 07 января 2020

Это не так, как Postgres работает. Процедуры не предназначены для возврата наборов результатов.

Если вы хотите использовать функцию возврата набора:

CREATE OR REPLACE function spr_getItems  ( 
  p_kind int = NULL,
  p_customerId varchar(256) = NULL,
  p_resourceIds varchar(2048) = NULL,
  p_referenceIds varchar(2048) = NULL
)
  returns table (kind text, customername text, customerid integer, resourcename text, resourceid integer, fullobjectstring text)
AS $$
  SELECT
    c.kind,
    c.name AS customerName,
    c.oid AS customerId,
    r.name AS resourceName,
    r.oid AS resourceId
    o.fullObject AS fullObjectString
  FROM m_customer c
  JOIN m_resource r
    ON r.oid = c.resourceOid
  LEFT JOIN m_object o
    ON o.customerOid = c.oid
      AND o.customerOid = p_customerId
  WHERE (c.kind = p_kind OR p_kind is NULL)
    AND (c.referenceOid IN (SELECT refTemp.oid FROM tvf_commaSeperatedStringToTable(p_referenceIds) refTemp) OR p_referenceIds is NULL)
    AND (r.oid IN (SELECT resTemp.oid FROM tvf_commaSeperatedStringToTable(p_resourceIds) resTemp) OR p_resourceIds is NULL); 
$$
LANGUAGE sql;

Вам также не нужен PL / pg SQL для простой инкапсуляции запроса, language sql подойдет просто отлично. ,

Затем используйте его как таблицу:

select *
from spr_getitems(....);

Обратите внимание, что я угадал типы данных в части returns table (...), вам нужно будет настроить их в соответствии с реальными типами, используемыми в ваших таблицах. .


Вам также не нужны субвыборы для обработки значений через запятую.

Например:

AND (c.referenceOid IN (SELECT refTemp.oid FROM tvf_commaSeperatedStringToTable(p_referenceIds) refTemp) OR p_referenceIds is NULL)

можно упростить до

AND (c.referenceOid = any (string_to_array(p_referenceIds, ',')  OR p_referenceIds is NULL)

Но передача нескольких значений в виде строки через запятую - плохой стиль кодирования для начала. Вы должны объявить эти параметры как массив и передать соответствующие массивы в функцию.

0 голосов
/ 06 января 2020

Ошибка относится к вызову функции ( spr_getshadowrefs ) внутри publi c .spr_getItems . Возможно, вы пытаетесь выполнить функцию spr_getshadowrefs , не помещая результат в какую-либо переменную.
Попробуйте использовать PERFORM при выполнении функции spr_getshadowrefs внутри publi c .spr_getItems .

0 голосов
/ 06 января 2020

Вы пробовали

EXEC spr_getItems p_kind = 0,
  p_customerId = NULL,
  p_resourceIds = NULL,
  p_referenceIds = NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...