Oracle
 sql >> база данни >  >> RDS >> Oracle

Проблем с променливите за свързване на Oracle, които не използват правилно индекса

Това наистина е по-голяма тема, но това е подходът, който според мен е най-лесният за прилагане и работи добре. Номерът е да използвате динамичен SQL, но го прилагайте така, че винаги да предавате един и същ брой параметри (необходими) И вие позволявате на Oracle да късо съединение, когато нямате стойност за параметър (това, което ви липсва настоящият ви подход). Например:

set serveroutput on
create or replace procedure test_param(p1 in number default null, p2 in varchar2 default null) as
  l_sql varchar2(4000);
  l_cur sys_refcursor;
  l_rec my_table%rowtype;
  l_ctr number := 0;
begin

  l_sql := 'select * from my_table where 1=1';
  if (p1 is not null) then
    l_sql := l_sql || ' and my_num_col = :p1';
  else
    -- short circuit for optimizer (1=1)
    l_sql := l_sql || ' and (1=1 or :p1 is null)';
  end if;

  if (p2 is not null) then
    l_sql := l_sql || ' and name like :p2';
  else
    -- short circuit for optimizer (1=1)
    l_sql := l_sql || ' and (1=1 or :p2 is null)';
  end if;

  -- show what the SQL query will be
  dbms_output.put_line(l_sql);

  -- note always have same param list (using)
  open l_cur for l_sql using p1,p2;

  -- could return this cursor (function), or simply print out first 10 rows here for testing
  loop
    l_ctr := l_ctr + 1;
    fetch l_cur
    into l_rec;
    exit when l_cur%notfound OR l_ctr > 10;

    dbms_output.put_line('Name is: ' || l_rec.name || ', Address is: ' || l_rec.address1);
  end loop;
  close l_cur;
end;

За да тествате, просто го стартирайте. Например:

set serveroutput on
-- using 0 param
exec test_param();
-- using 1 param
exec test_param(123456789);
-- using 2 params
exec test_param(123456789, 'ABC%');

В моята система използваната таблица е над 100 мм редове с индекс в полето за число и поле за име. Връща се почти мигновено. Също така имайте предвид, че може да не искате да правите избор *, ако не се нуждаете от всички колони, но аз съм малко мързелив и използвам %rowtype за този пример.

Надявам се това да помогне



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Избройте всички функции в базата данни на Oracle

  2. Изберете последния ред за всяка група от oracle

  3. Агрегиране на редове в Oracle SQL оператор

  4. Как мога да поправя тази грешка:не се поддържа SQL92?

  5. Oracle:как да INSERT, ако ред не съществува