Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Trả về kết quả ngay cả cho các phần tử trong danh sách IN không tồn tại trong bảng

Từ phía SQL, bạn có thể xác định một kiểu bảng và sử dụng kiểu đó để kết hợp với dữ liệu thực của bạn, chẳng hạn như:

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;
/

Bản trình diễn SQL Fiddle với hàm trình bao bọc để bạn có thể truy vấn trực tiếp, điều này mang lại:

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

Từ Java, bạn có thể xác định một ARRAY dựa trên kiểu bảng, điền từ một mảng Java và gọi hàm trực tiếp; biến ràng buộc tham số duy nhất của bạn là ARRAY và bạn nhận được tập hợp kết quả mà bạn có thể lặp lại như bình thường.

Như một phác thảo về phía 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));
}

Điều này mang lại:

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

Như Maheswaran Ravisankar đã đề cập, điều này cho phép bất kỳ số phần tử nào được chuyển qua; bạn không cần biết có bao nhiêu phần tử tại thời điểm biên dịch (hoặc xử lý tối đa lý thuyết), bạn không bị giới hạn bởi số lượng biểu thức tối đa được phép trong IN hoặc bằng độ dài của một chuỗi được phân tách và bạn không phải soạn và phân tách một chuỗi để chuyển nhiều giá trị.

Như ThinkJet đã chỉ ra, nếu bạn không muốn tạo loại bảng của riêng mình, bạn có thể sử dụng một bộ sưu tập được xác định trước, được trình bày ở đây; chức năng chính giống nhau ngoài việc khai báo tham số:

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

Hàm wrapper điền mảng hơi khác một chút, nhưng về phía Java, bạn chỉ cần thay đổi dòng này:

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

Sử dụng điều này cũng có nghĩa là (như ThinkJet cũng đã chỉ ra!) Rằng bạn có thể chạy truy vấn độc lập ban đầu của mình mà không cần xác định một hàm:

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).

Và điều đó có nghĩa là bạn có thể gọi truy vấn trực tiếp từ 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));
}

... mà bạn có thể thích.

Có một ODCIVARCHAR2LIST được xác định trước nhập quá, nếu bạn thực sự đang chuyển các chuỗi - mã gốc của bạn dường như đang hoạt động với các chuỗi mặc dù chúng chứa số, vì vậy không chắc bạn thực sự cần cái nào.

Vì các loại này được định nghĩa là VARRAY(32767) bạn bị giới hạn ở các giá trị 32k, trong khi việc xác định bảng của riêng bạn sẽ loại bỏ hạn chế đó; nhưng rõ ràng điều đó chỉ quan trọng nếu bạn chuyển nhiều giá trị.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách cài đặt SQLcl trên máy Mac

  2. Phát hiện xem một giá trị có chứa ít nhất một chữ số trong Oracle hay không

  3. Định cấu hình Hibernate để sử dụng SYS_GUID () của Oracle cho Khóa chính

  4. ojdbc14.jar so với ojdbc6.jar

  5. làm thế nào để chuyển đổi csv sang bảng trong oracle