Разбивка на страницы процедур Oracle, возвращающая больше строк, чем ожидалось

#sql #oracle #stored-procedures #oracle11g

#sql #Oracle #хранимые процедуры #oracle11g

Вопрос:

Это сокращенная процедура для примера. Проблема, с которой я сталкиваюсь, заключается в том, что когда я перехожу на следующую страницу в своем приложении, она возвращает 5, затем 10, затем 15, затем 10. Я хочу возвращать только 5 каждый раз. Похоже, это происходит, когда дата убывает.

 procedure GET_DATA( p_sort_col IN VARCHAR2, p_sort_order IN VARCHAR2,
  p_page_index IN NUMBER DEFAULT null,
  p_page_size IN NUMBER DEFAULT null, p_cursor  out l_cursor)
AS
begin
OPEN p_cursor FOR
    select * from (
select* from (select rownum rn, Name, DateCol, ROW_NUMBER() Over( ORDER BY 
 CASE
        WHEN p_sort_col = 'Name' and p_sort_order = 'asc' THEN
         Name
END ASC,
  CASE 
            WHEN p_sort_col = 'DateCol' and p_sort_order = 'asc' THEN
           DateCol
     END ASC,
CASE 
        WHEN p_sort_col = 'Name' and p_sort_order = 'desc' THEN
         Name
     END DESC,
      CASE 
            WHEN p_sort_col = 'DateCol' and p_sort_order = 'desc' THEN
            DateCol
     END DESC) from gdpr_document_manager_audit  
     ) where  rownum < ((p_page_index * p_page_size)   1 )         
)WHERE rn >= (((p_page_index-1) * p_page_size));
END GET_DATA;
 

фактический запрос

Комментарии:

1. Разбивка на страницы без упорядочения имеет мало смысла.

2. @TheImpaler у него есть порядок см. Порядок по ключевым словам?

3. Я вижу только ORDER BY внутри ROW_NUMBER() функции. Однако это не влияет на порядок результирующего набора.

4. @TheImpaler это на самом деле.

5. @TheImpaler когда я перехожу на следующую страницу в приложении, он сначала упорядочивает результирующий набор, а затем разбивает его на страницы, спасибо за ввод, есть ли действительно полезные советы по проблеме разбивки на страницы?

Ответ №1:

Я предполагаю, что

 select event_type, doc_page, application_number, 
       document_reference, username, application_year, 
       full_name, date_and_time
  from gdpr_document_manager_audit
 ORDER BY 
   CASE
     WHEN p_sort_col = 'EventType' and p_sort_order = 'asc' THEN event_type 
     WHEN p_sort_col = 'ApplicationYear' and p_sort_order = 'asc' THEN application_year 
     WHEN p_sort_col = 'ApplicationNumber' and p_sort_order = 'asc' THEN application_number 
     WHEN p_sort_col = 'DocumentReference' and p_sort_order = 'asc' THEN doument_reference 
     WHEN p_sort_col = 'Username' and p_sort_order = 'asc' THEN username 
     WHEN p_sort_col = 'Name' and p_sort_order = 'asc' THEN full_name 
   END ASC,
   CASE 
     WHEN p_sort_col = 'DateAndTime' and p_sort_order = 'asc' THEN date_and_time
   END ASC,
   CASE 
     WHEN p_sort_col = 'EventType' and p_sort_order = 'desc' THEN event_type 
     WHEN p_sort_col = 'ApplicationYear' and p_sort_order = 'desc' THEN application_year 
     WHEN p_sort_col = 'ApplicationNumber' and p_sort_order = 'desc' THEN application_number 
     WHEN p_sort_col = 'DocumentReference' and p_sort_order = 'desc' THEN document_reference 
     WHEN p_sort_col = 'Username' and p_sort_order = 'desc' THEN username 
     WHEN p_sort_col = 'Name' and p_sort_order = 'desc' THEN full_name 
 END DESC,
 CASE 
     WHEN p_sort_col = 'DateAndTime' and p_sort_order = 'desc' THEN date_and_time
 END DESC
 

возвращает нужные данные в нужном порядке, только без разбивки на страницы. Для простоты я буду ссылаться на этот запрос, как #base_query# в моем ответе ниже. Если это так, и учитывая, что вам необходимо поддерживать более старую версию Oracle, вы бы преобразовали ее в запрос с разбивкой на страницы следующим образом

 select * 
  from ( select /*  FIRST_ROWS(n) */ 
                a.*, ROWNUM rnum 
           from ( #base_query# ) a 
          where ROWNUM <= ((p_page_index * p_page_size)   p_page_size ) ) 
  where rnum  >= (((p_page_index-1) * p_page_size));
 

используя вычисления, которые у вас есть для минимальной и максимальной строки, которую вы хотите вернуть. Вы не сообщили нам, какие значения вы передаете для различных параметров. Если мы предполагаем, что p_page_index для первой страницы это 1 (некоторые люди используют индексацию на основе 0), вы, вероятно, действительно захотите

 select * 
  from ( select /*  FIRST_ROWS(n) */ 
                a.*, ROWNUM rnum 
           from ( #base_query# ) a 
          where ROWNUM <= (p_page_index * p_page_size) 
  where rnum  >= (p_page_index-1) * p_page_size   1;
 

Итак, если p_page_index = 1 и p_page_size = 10, вы получите строки от 1 до 10. Если p_page_index = 2 и p_page_size = 10, вы получите строки с 11 по 20. и т.д.

Комментарии:

1. Все та же проблема, проблема заключается в вычислении для разбивки на страницы. @JustinCave

2. @PaulDocks — Похоже, вы пытались отредактировать мой ответ, сказав, что получили то, что хотели. Но затем добавлен комментарий, что у вас все еще есть проблема.

3. да, извините, хотел также удалить фактический запрос. у меня все та же проблема. проблема заключается в логике разбивки на страницы. @JustinCave

4. @PaulDocks — я сделал несколько предположений о том, какие значения вы передаете для параметров, и обновил свой ответ. Если вы используете индексацию на основе 0, это другое. Может быть проще создать локальные переменные для минимальной и максимальной строки, которые затем можно распечатать / проверить для отладки.

5. 1,2,3,4 и т.д. для индекса страницы и 5 для размера страницы каждый раз @JustinCave