Как я могу создать функцию SQL с параметром? - PullRequest
2 голосов
/ 14 марта 2012

Следующий код возвращает одно поле, строку, основанную на вводе, где написано «28».

SELECT data.id, LTRIM(SYS_CONNECT_BY_PATH(name, ', '),',') conc_names
  FROM (
     SELECT id, name, ROW_NUMBER() OVER (order by name) rownumber, COUNT(*) OVER () cnt
      FROM (
         SELECT es.EVENT_ID as id, s.SERVICE_NAME as name FROM DT_SERVICES s
            JOIN DT_EVENT_SERVICE es ON s.SERVICE_ID = es.SERVICE_ID
         WHERE es.EVENT_ID = 28
      )
) data
WHERE rownumber = cnt
START WITH rownumber = 1
CONNECT BY PRIOR rownumber = rownumber-1;

Как я могу создать из этого функцию SQL, чтобы я мог передавать любое число (вместо 28) и функция возвращала бы любой результат этого выбора?

Я пытался создать его, но получаю ошибки компиляции.

Текущий SQL для создания функции

create or replace function "DT_SERVICE_STRING" (id in VARCHAR2)
  return VARCHAR2 is
begin
  DECLARE 
     result VARCHAR(200);
  SELECT data.id, LTRIM(SYS_CONNECT_BY_PATH(name, ', '),',') conc_names
    INTO result
    FROM (
      SELECT id, name, ROW_NUMBER() OVER (order by name) rownumber, COUNT(*) OVER () cnt
      FROM (
        SELECT es.EVENT_ID as id, s.SERVICE_NAME as name FROM DT_SERVICES s
        JOIN DT_EVENT_SERVICE es ON s.SERVICE_ID = es.SERVICE_ID
        WHERE es.EVENT_ID = id
      )
  ) data
  WHERE rownumber = cnt
  START WITH rownumber = 1
  CONNECT BY PRIOR rownumber = rownumber-1;

  return result;
end;​

Ошибка:
Компиляция не удалась, строка 7 (15:22:21) PLS-00103: Обнаружен символ «ВЫБОР» при ожидании одного из следующих действий: функция начала прагма тип подтипа текущий удаление курсора ранее

Ответы [ 2 ]

4 голосов
/ 14 марта 2012

Предполагая, что вам нужна функция PL / SQL, которая вызывается из оператора SQL (функция не может быть определена в SQL), звучит так, будто вам нужно что-то вроде

CREATE OR REPLACE FUNCTION get_conc_names( p_event_id IN dt_event_service.event_id%type )
  RETURN VARCHAR2
IS
  l_conc_names VARCHAR2(32676); 
  -- You may want a smaller variable if you know the result will be smaller
BEGIN
  SELECT LTRIM(SYS_CONNECT_BY_PATH(name, ', '),',') conc_names
    INTO l_conc_names
    FROM (
      SELECT id, name, ROW_NUMBER() OVER (order by name) rownumber, COUNT(*) OVER () cnt
        FROM (SELECT es.EVENT_ID as id, s.SERVICE_NAME as name 
                FROM DT_SERVICES s
                     JOIN DT_EVENT_SERVICE es ON s.SERVICE_ID = es.SERVICE_ID
               WHERE es.EVENT_ID = p_event_id )
          ) data
   WHERE rownumber = cnt
   START WITH rownumber = 1
 CONNECT BY PRIOR rownumber = rownumber-1;
  RETURN l_conc_names;
END;

На основе кодаВы только что написали, кажется, что вам просто нужно избавиться от DECLARE и переместить объявление локальной переменной result до BEGIN и после IS.

0 голосов
/ 16 марта 2012

Я думаю, что аналитические функции должны находиться внутри внутреннего встроенного представления, а затем внешнее встроенное представление может их выбирать - так я всегда делал это.Попробуйте вместо этого:

CREATE OR REPLACE FUNCTION get_conc_names( p_event_id IN dt_event_service.event_id%type ) 
  RETURN VARCHAR2 
IS 
  l_conc_names VARCHAR2(32676);  
  -- You may want a smaller variable if you know the result will be smaller 
BEGIN 
  SELECT LTRIM(SYS_CONNECT_BY_PATH(name, ', '),',') conc_names 
    INTO l_conc_names 
    FROM ( 
      SELECT id, name, rownumber, cnt 
        FROM (SELECT es.EVENT_ID as id
                    ,s.SERVICE_NAME as name
                    ,ROW_NUMBER() OVER (order by name) as rownumber
                    ,COUNT(*) OVER () as cnt
                FROM DT_SERVICES s 
                     JOIN DT_EVENT_SERVICE es ON s.SERVICE_ID = es.SERVICE_ID 
               WHERE es.EVENT_ID = p_event_id ) 
             ) data 
    WHERE rownumber = cnt 
    START WITH rownumber = 1 
    CONNECT BY PRIOR rownumber = rownumber-1; 
  RETURN l_conc_names; 
END; 
...