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

Oracle:Cách chọn hàng hiệu quả bằng danh sách khóa

Việc chuyển các giá trị cho IN không phải là một phương pháp hay điều kiện như nối chuỗi. Tất nhiên, điều đầu tiên là bảo mật và tính đúng đắn, nhưng điểm tiếp theo là hiệu suất.
Mỗi lần bạn gọi công cụ cơ sở dữ liệu câu lệnh sẽ phân tích cú pháp nó, hãy xây dựng một kế hoạch truy vấn và sau đó thực hiện các hành động được chỉ định trong câu lệnh SQL.
Nếu bạn xây dựng văn bản truy vấn từ đầu mỗi lần, sau đó tất cả ba giai đoạn được thực thi mỗi lần.
Nhưng nếu bạn sử dụng các biến liên kết mọi lúc, truy vấn trông giống nhau, vì vậy cơ sở dữ liệu sử dụng kế hoạch truy vấn được lưu trong bộ nhớ cache để tăng tốc độ thực thi truy vấn. Thậm chí bạn có thể gọi oci_parse () chỉ một lần và sử dụng lại $ stmt biến có tập hợp các tham số được cung cấp khác nhau.
Vì vậy, để có hiệu suất tốt nhất, bạn phải sử dụng biến bind và điền nó vào mảng bằng cách sử dụng oci_bind_array_by_name .

Điều bổ sung là truy xuất kết quả bằng cách sử dụng oci_fetch_all có thể hoạt động nhanh hơn việc đọc kết quả được đặt từng hàng một, nhưng nó phụ thuộc vào logic của kết quả xử lý.

Cập nhật

Có vẻ như việc truyền các tham số mảng chỉ hoạt động nếu bạn thực thi khối PL / SQL và không thể sử dụng nó với các câu lệnh SQL. Nhưng một khả năng khác là sử dụng các bộ sưu tập để chuyển danh sách các giá trị tham số. Có thể thỏa mãn các điều kiện của câu hỏi ngay cả với các mảng, nhưng cách này kém thanh lịch hơn.
Bên cạnh một số cách khác để truy vấn cơ sở dữ liệu, còn có những thứ như cài đặt hệ thống. Trong trường hợp PHP, có một số tham số trong php.ini tệp kiểm soát tương tác với Oracle. Một trong số chúng ( oci8.statement_cache_size ) liên quan đến hiệu suất và bộ đệm ẩn truy vấn.

Ví dụ

Tất cả các ví dụ đều sử dụng cùng một thiết lập dữ liệu trong Oracle.
Để chuyển dữ liệu, tôi chọn SYS.ODCIVarchar2List được xác định trước. nhưng cũng có thể xác định kiểu tùy chỉnh với các đặc điểm giống nhau (được trình bày trong ví dụ thiết lập dữ liệu). Dưới đây là mã để phân tích thiết lập lược đồ dữ liệu và nguyên tắc sử dụng tập hợp trong DML.

SQLFiddle

create table myTable(value varchar2(100), key varchar2(100))
/

insert into myTable(value, key)
select * from (
  select 'apple', 'apple_one' from dual union all
  select 'apple', 'apple_two' from dual union all
  select 'banana', 'banana_one' from dual union all
  select 'orange', 'orange_one' from dual union all
  select 'orange', 'orange_two' from dual union all
  select 'potato', 'potato_one' from dual
)
/

create or replace type TCustomList as table of varchar2(4000)
/

create or replace package TestPackage as

  type TKeyList is table of varchar2(1000) index by binary_integer;

  function test_select(pKeyList in out TKeyList) return sys_refcursor;

end;
/

create or replace package body TestPackage is

  function test_select(pKeyList in out TKeyList) return sys_refcursor
  is               
    vParam sys.ODCIVarchar2List := sys.ODCIVarchar2List();
    vCur sys_refcursor;  
    vIdx binary_integer;
  begin                

    vIdx := pKeyList.first;
    while(vIdx is not null) loop
      vParam.Extend;
      vParam(vParam.last) := pKeyList(vIdx);
      vIdx := pKeyList.next(vIdx);
    end loop;

    open vCur for 
      select * from myTable where value in (select column_value from table(vParam))    
    ;

    return vCur;
  end;

end;
/

Truy vấn để chứng minh bộ sưu tập:

--select by value list
select * from myTable 
where value in (
        select column_value 
        from table(Sys.ODCIVarchar2List('banana','potato'))
      )
/

--same with custom type
select * from myTable 
where value in (
        select column_value 
        from table(TCustomList('banana','potato'))
      )
/

--same with demonstration of casting 
select * from myTable 
where value in (
        select column_value 
        from table(cast(TCustomList('banana','potato') as Sys.ODCIVarchar2List))
      )
/

Ví dụ 1 - gọi từ PHP bằng cách sử dụng bộ sưu tập

<?php
  $keyList = array('apple', 'potato');

  $conn = oci_pconnect("user_name", "user_password", "SERVER_TNS_NAME");

  $stmt = oci_parse($conn, "SELECT * FROM myTable where value in (select column_value from table(:key_list))");

  $coll = oci_new_collection($conn, 'ODCIVARCHAR2LIST','SYS');

  for ($i=0; $i < count($keyList); $i++) {
    $coll->append($keyList[$i]);
  }

  oci_bind_by_name($stmt, 'key_list', $coll, -1, OCI_B_NTY);

  oci_execute($stmt);

  while($row = oci_fetch_array($stmt, OCI_ASSOC)) {
      echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
  }
  echo "---\n";

  $coll->free();

  //-- Run statement another time with different parameters
  //-- without reparsing.

  $coll = oci_new_collection($conn, 'ODCIVARCHAR2LIST','SYS');
  $coll->append('banana');
  oci_bind_by_name($stmt, 'key_list', $coll, -1, OCI_B_NTY);

  oci_execute($stmt);

  while($row = oci_fetch_array($stmt, OCI_ASSOC)) {
      echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
  }
  echo "---\n";

  $coll->free();

  oci_free_statement($stmt);
  oci_close($conn);
?>

Ví dụ 2 - Gọi từ PHP bằng cách sử dụng mảng và gói

<?php
  $keyList = array('apple', 'potato');

  $conn = oci_pconnect("user_name", "user_password", "SERVER_TNS_NAME");

  $stmt = oci_parse($conn, "begin :cur := TestPackage.test_select(:key_list); end;");

  $curs = oci_new_cursor($conn);

  oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);
  oci_bind_by_name($stmt, "cur", $curs, -1, OCI_B_CURSOR);

  oci_execute($stmt);
  oci_execute($curs);

  while($row = oci_fetch_array($curs, OCI_ASSOC)) {
      echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
  }
  echo "---\n";


  //-- Run statement another time with different parameters
  //-- without reparsing.

  $keyList = array('banana');

  oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);

  oci_execute($stmt);
  oci_execute($curs);

  while($row = oci_fetch_array($curs, OCI_ASSOC)) {
      echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
  }
  echo "---\n";

  oci_free_statement($stmt);
  oci_close($conn);
?>

Ví dụ 3 - gọi từ PHP bằng cách sử dụng mảng và khối ẩn danh

<?php
  $keyList = array('apple', 'potato');

  $conn = oci_pconnect("user_name", "user_password", "SERVER_TNS_NAME");

  $stmt = oci_parse($conn, "
    declare
      type TKeyList is table of varchar2(4000) index by binary_integer;

      pKeyList TKeyList := :key_list;
      vParam   sys.ODCIVarchar2List := sys.ODCIVarchar2List();
      vIdx     binary_integer;
    begin

      -- Copy PL/SQL array to a type which allowed in SQL context
      vIdx := pKeyList.first;
      while(vIdx is not null) loop
        vParam.Extend;
        vParam(vParam.last) := pKeyList(vIdx);
        vIdx := pKeyList.next(vIdx);
      end loop;

      open :cur for select * from myTable where value in (select column_value from table(vParam));
    end;
  ");

  $curs = oci_new_cursor($conn);

  oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);
  oci_bind_by_name($stmt, "cur", $curs, -1, OCI_B_CURSOR);

  oci_execute($stmt);
  oci_execute($curs);

  while($row = oci_fetch_array($curs, OCI_ASSOC)) {
      echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
  }
  echo "---\n";


  //-- Run statement another time with different parameters
  //-- without reparsing.

  $keyList = array('banana');

  oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);

  oci_execute($stmt);
  oci_execute($curs);

  while($row = oci_fetch_array($curs, OCI_ASSOC)) {
      echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
  }
  echo "---\n";

  oci_free_statement($stmt);
  oci_close($conn);
?>


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Gọi một hàm PL SQL với tham số đối tượng trong java

  2. Máy khách Oracle ORA-12541:TNS:không có người nghe

  3. AWS Python Lambda với Oracle - Thế hệ OID không thành công ngay cả sau khi thêm HOSTALIASES

  4. Biểu thức chính quy để trả về số sau chuỗi đã so khớp trong oracle

  5. Đóng hay không đóng Kết nối Oracle?