Как использовать параметр функции в курсоре, который включен в динамический SQL в функциях Postgres? - PullRequest
0 голосов
/ 08 февраля 2019

Создал эту функцию Postgres, которая работает нормально, но фактическим требованием является передача входного параметра в функции в курсор, который использует динамический SQL следующим образом:

Ниже приведена функция

CREATE OR REPLACE FUNCTION ssp2_pcat.find_shift_dates (date_to_find date)
  RETURNS void
  LANGUAGE 'plpgsql'

  COST 100
  VOLATILE 
AS $BODY$

DECLARE
C1 CURSOR FOR
SELECT TABLE_NAME, 'SELECT COUNT(*) FROM ' || TABLE_NAME || ' WHERE ' || 
COLUMN_NAME || ' = '||
'CASE WHEN ' || COLUMN_NAME || ' LIKE ' || '''%START%'''||' THEN 
 date_to_find ELSE date_to_find-1 END;' SQL_TEXT 
FROM (
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME IN (SELECT TABLE_NAME FROM RESET_DATES WHERE RESET_IT = 
'Y') AND
UPPER(DATA_TYPE) = 'DATE' 
AND (COLUMN_NAME LIKE '%START%' OR COLUMN_NAME LIKE '%END%')
AND (COLUMN_NAME NOT LIKE '%TEST%' 
AND COLUMN_NAME NOT LIKE '%PCAT%' 
AND COLUMN_NAME NOT LIKE '%ORDER%' 
AND COLUMN_NAME NOT LIKE '%SEASON%' 
AND COLUMN_NAME NOT LIKE '%_AT')
ORDER BY 1, 2) A;

END_COUNT     INTEGER := 0;
START_COUNT   INTEGER := 0;
TABLENAME     VARCHAR(32) := 'ALFU';
l_start       TIMESTAMP;
l_end         TIMESTAMP;
Time_Taken    VARCHAR(20);

BEGIN
  l_start  := clock_timestamp();
  DELETE FROM SHIFT_DATES_COUNT;
  FOR I IN C1 LOOP
    IF I.TABLE_NAME <> TABLENAME THEN
      INSERT INTO SHIFT_DATES_COUNT VALUES (TABLENAME, START_COUNT, 
      END_COUNT, current_timestamp::timestamp(0));
      TABLENAME := I.TABLE_NAME;
      END_COUNT := 0;
      START_COUNT := 0;
    END IF;
    IF STRPOS(I.SQL_TEXT, 'END') > 0 THEN
     EXECUTE I.SQL_TEXT INTO END_COUNT;
     RAISE NOTICE '% ', ('END: ' || I.SQL_TEXT); 
    ELSE
     EXECUTE I.SQL_TEXT INTO START_COUNT;
     RAISE NOTICE '% ', ('START: ' || I.SQL_TEXT); 
    END IF;
  END LOOP;
 INSERT INTO SHIFT_DATES_COUNT VALUES (TABLENAME, START_COUNT, END_COUNT, 
 current_timestamp::timestamp(0));
 RAISE NOTICE '% ', ('INSERT INTO SHIFT_DATES_COUNT Done...'); 
 l_end  := clock_timestamp();
 Time_Taken := (l_end-l_start); 

 RAISE NOTICE '% ', ('FIND_SHIFT_DATES Took: ' || Time_Taken );
END;

$BODY$;

Пожалуйста, дайте мне знать, как я могу использовать входной параметр date_to_find в Динамическом SQL в Курсоре в вышеуказанной функции.

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Вы можете использовать несвязанный курсор, выборку предложения, чтобы получить данные от курсора, и выйти, если не найдено, что он не завершен, например:

CREATE OR REPLACE  FUNCTION example (p_name text)  RETURNS void LANGUAGE 'plpgsql' AS $$

DECLARE
C1 refcursor; 
res record;
BEGIN
OPEN c1 FOR EXECUTE 'SELECT * FROM pg_database WHERE datname like ''%'||p_name||'%''';


 LOOP
FETCH c1 INTO res;
EXIT WHEN not found;
raise notice 'value datname: %',res.datname;
END LOOP;

CLOSE c1;
RETURN;
END;   $$;


--in my case
select example ('test')
NOTICE:  value datname: test
NOTICE:  value datname: test_msmov
NOTICE:  value datname: test_resources
NOTICE:  value datname: test_load_table
NOTICE:  value datname: test_resources2
Total query runtime: 63 msec
1 row retrieved.
0 голосов
/ 10 февраля 2019

Вы можете использовать предложение EXECUTE для открытого курсора, см. Документацию PostgreSQL https://www.postgresql.org/docs/10/plpgsql-cursors.html#PLPGSQL-CURSOR-OPENING Пример:

OPEN curs1 FOR EXECUTE format('SELECT * FROM %I WHERE col1 = $1',tabname) USING keyvalue;
...