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

Връщане на резултат дори за елементи в списъка IN, които не съществуват в таблицата

От страна на SQL можете да дефинирате тип таблица и да го използвате, за да се присъедините към вашите реални данни, нещо като:

create type my_array_type as table of number
/

create or replace function f42 (in_array my_array_type)
return sys_refcursor as
  rc sys_refcursor;
begin
  open rc for
    select a.column_value as id,
      case when t.id is null then 'missing'
        else 'present' end as status
    from table(in_array) a
    left join t42 t on t.id = a.column_value
    order by id;

  return rc;
end f42;
/

Демонстрация на SQL Fiddle с функция за обвивка, за да можете да я заявите директно, което дава:

        ID STATUS             
---------- --------------------
         1 present              
         2 present              
         3 present              
         4 missing              
         8 missing              
        23 present              

От Java можете да дефинирате ARRAY въз основа на типа на таблицата, попълване от масив на Java и извикване на функцията директно; вашата променлива за свързване с един параметър е ARRAY , и получавате обратно набор от резултати, който можете да повторите както обикновено.

Като очертание на страната на Java:

int[] ids = { 1, 2, 3, 4, 8, 23 };
ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("MY_ARRAY_TYPE",
  conn);
oracle.sql.ARRAY ora_ids = new oracle.sql.ARRAY(aDesc, conn, ids);

cStmt = (OracleCallableStatement) conn.prepareCall("{ call ? := f42(?) }");
cStmt.registerOutParameter(1, OracleTypes.CURSOR);
cStmt.setArray(2, ora_ids);
cStmt.execute();
rSet = (OracleResultSet) cStmt.getCursor(1);

while (rSet.next())
{
    System.out.println("id " + rSet.getInt(1) + ": " + rSet.getString(2));
}

Което дава:

id 1: present
id 2: present
id 3: present
id 4: missing
id 8: missing
id 23: present

Както споменава Махесваран Рависанкар, това позволява преминаването на произволен брой елементи; не е нужно да знаете колко елемента има по време на компилиране (или да се справяте с теоретичен максимум), не сте ограничени от максималния брой изрази, разрешени в IN или по дължината на единичен разделен низ и не е нужно да съставяте и декомпозирате низ, за ​​да предадете множество стойности.

Както ThinkJet посочи, ако не искате да създавате свой собствен тип таблица, можете да използвате предварително дефинирана колекция, демонстрирана тук; основната функция е същата, освен декларацията на параметъра:

create or replace function f42 (in_array sys.odcinumberlist)
return sys_refcursor as
...    

Функцията wrapper попълва масива малко по-различно, но от страна на Java трябва само да промените този ред:

ArrayDescriptor aDesc =
  ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );

Използването на това също означава (както ThinkJet също посочи!), че можете да стартирате оригиналната си самостоятелна заявка, без да дефинирате функция:

select a.column_value as id,
case when t.id is null then 'missing'
else 'present' end as status
from table(sys.odcinumberlist(1, 2, 3, 4, 8, 23)) a
left join t42 t on t.id = a.column_value
order by id;

(SQL Fiddle).

А това означава, че можете да извикате заявката директно от Java:

int[] ids = { 1, 2, 3, 4, 8, 23 };
ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );
oracle.sql.ARRAY ora_ids = new oracle.sql.ARRAY(aDesc, conn, ids);

sql = "select a.column_value as id, "
    + "case when t.id is null then 'missing' "
    + "else 'present' end as status "
    + "from table(?) a "
    + "left join t42 t on t.id = a.column_value "
    + "order by id";
pStmt = (OraclePreparedStatement) conn.prepareStatement(sql);
pStmt.setArray(1, ora_ids);
rSet = (OracleResultSet) pStmt.executeQuery();

while (rSet.next())
{
    System.out.println("id " + rSet.getInt(1) + ": " + rSet.getString(2));
}

... което може да предпочетете.

Има предварително дефиниран ODCIVARCHAR2LIST напишете също, ако всъщност предавате низове - оригиналният ви код изглежда работи с низове, въпреки че съдържат числа, така че не сте сигурни от кои наистина се нуждаете.

Тъй като тези типове са дефинирани като VARRAY(32767) сте ограничени до 32k стойности, докато дефинирането на вашата собствена таблица премахва това ограничение; но очевидно това има значение само ако предавате много стойности.



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

  2. Как да използвам ключовата дума 'as' за псевдоним на таблица в Oracle?

  3. Base64 кодиране и декодиране в oracle

  4. Как да получите тримесечие от дата в Oracle?

  5. Как да се свържа с отдалечена Oracle DB с PL/SQL Developer?