2011-10-19 44 views
38

Tôi có một câu hỏi liên quan đến các biến liên kết có thể được sử dụng trong câu lệnh SQL động trong PL/SQL.Sử dụng các biến liên kết với mệnh đề SELECT INTO động trong PL/SQL

Ví dụ, tôi biết rằng đây là hợp lệ:

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER 
IS 
    v_query_str VARCHAR2(1000); 
    v_num_of_employees NUMBER; 
BEGIN 
    v_query_str := 'SELECT COUNT(*) FROM emp_' 
       || p_loc 
       || ' WHERE job = :bind_job';       
    EXECUTE IMMEDIATE v_query_str 
    INTO v_num_of_employees 
    USING p_job; 
    RETURN v_num_of_employees; 
END; 
/

tôi đã tự hỏi nếu bạn có thể sử dụng một biến ràng buộc trong một tuyên bố chọn như thế này

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER 
IS 
    v_query_str VARCHAR2(1000); 
    v_num_of_employees NUMBER; 
BEGIN 
    v_query_str := 'SELECT COUNT(*) INTO :into_bind FROM emp_' 
       || p_loc 
       || ' WHERE job = :bind_job';       
    EXECUTE IMMEDIATE v_query_str 
    USING out v_num_of_employees, p_job; 
    RETURN v_num_of_employees; 
END; 
/

Lưu ý tôi đã sử dụng một SELECT INTO tuyên bố như chuỗi dyamic của tôi và sử dụng một biến liên kết trong mệnh đề INTO.

Tôi hiện đang đi du lịch và sẽ không có quyền truy cập vào máy tính của mình ở nhà trong một vài ngày, nhưng điều này đã khiến tôi lo lắng một chút. Đã thử đọc tham chiếu PL/SQL nhưng chúng không có ví dụ về lựa chọn như thế này.

Cảm ơn

+0

Liên quan: http://stackoverflow.com/q/25489002/1461424 – Krumia

Trả lời

24

Không, bạn không thể sử dụng biến liên kết theo cách đó. Trong ví dụ thứ hai của bạn :into_bind trong v_query_str chỉ là một giữ chỗ cho giá trị của biến v_num_of_employees. chọn của bạn vào tuyên bố sẽ biến thành cái gì đó như:

SELECT COUNT(*) INTO FROM emp_... 

vì giá trị của v_num_of_employeesnull tại EXECUTE IMMEDIATE.

Ví dụ đầu tiên của bạn trình bày cách chính xác để ràng buộc giá trị trả lại cho một biến.

Sửa

Những poster ban đầu đã thay đổi nội dung các khối mã thứ hai mà tôi đề cập trong câu trả lời của tôi để sử dụng chế độ OUT tham số cho v_num_of_employees thay vì chế độ mặc định IN. Sửa đổi này làm cho cả hai ví dụ về chức năng tương đương.

+0

Ồ điều đó có nghĩa, ': into_bind' sẽ được thay thế khi nó thực sự chạy. Trong ví dụ đầu tiên tôi đã viết, liệu nó có còn đang sử dụng một biến liên kết trong mệnh đề INTO không? Lý do tôi muốn thử cách thứ hai, là vì nó sử dụng các biến liên kết. – BYS2

+2

@ BYS2: Có, bạn có thể sử dụng với chế độ tham số 'OUT'. Tuy nhiên tôi thích 'EXECUTE IMMEDIATE INTO' cho rõ ràng hơn. – user272735

+0

Oh ok, tuyệt vời để hoạt động tốt! được thôi, cảm ơn :) – BYS2

18

Đặt câu lệnh chọn trong khối PL/SQL động.

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER 
IS 
    v_query_str VARCHAR2(1000); 
    v_num_of_employees NUMBER; 
BEGIN 
    v_query_str := 'begin SELECT COUNT(*) INTO :into_bind FROM emp_' 
       || p_loc 
       || ' WHERE job = :bind_job; end;'; 
    EXECUTE IMMEDIATE v_query_str 
    USING out v_num_of_employees, p_job; 
    RETURN v_num_of_employees; 
END; 
/
+0

Ahh tôi hiểu rồi, cảm ơn! Trên một mặt lưu ý, bạn có bất kỳ ý tưởng mà cách nào là tốt hơn? đóng gói SELECT INTO trong một khối như bạn đã làm hoặc sử dụng mệnh đề INTO của câu lệnh EXECUTE IMMEDIATE như tôi đã làm trong ví dụ đầu tiên của tôi. Cả hai đều sử dụng các biến liên kết? bất kỳ sự khác biệt về hiệu quả? – BYS2

+1

Tôi đồng ý với những người khác rằng phương pháp đầu tiên (SQL động) tốt hơn nhiều so với phương thức thứ hai (PL/SQL động). PL/SQL động rất hiếm và hầu như không cần thiết. Dựa trên một số thử nghiệm đơn giản, tôi đã không thấy bất kỳ sự khác biệt hiệu suất giữa hai, nhưng tôi hy vọng phương pháp PL/SQL động sẽ chậm hơn một chút trong một số trường hợp. Phương thức PL/SQL động thực sự tạo ra 3 biến liên kết: 2 cho khối PL/SQL (mặc dù không được bắt giữ trong V $ SQL_BIND_CAPTURE), và 1 cho truy vấn SQL . Quirks như thế có thể điều chỉnh và gỡ lỗi rất khó. –

+0

Oh ok, cảm ơn rất nhiều vì lời khuyên của bạn! Không thể đặt câu trả lời của bạn thành câu trả lời vì về mặt kỹ thuật, đó không phải là câu hỏi của tôi, nhưng tôi là tất cả vì đã học nên điều này là tốt để biết: D – BYS2

24

Theo tôi, khối PL/SQL động hơi mơ hồ. Trong khi rất linh hoạt, cũng khó điều chỉnh, khó gỡ lỗi và khó tìm ra những gì đang diễn ra. Phiếu bầu của tôi đi vào tùy chọn đầu tiên của bạn,

EXECUTE IMMEDIATE v_query_str INTO v_num_of_employees USING p_job; 

Cả hai sử dụng các biến ràng buộc, nhưng trước tiên, đối với tôi, là redeable hơn và tuneable hơn tùy chọn @jonearles.

+0

Ok cảm ơn bạn vì thông tin đó, vì cả hai đều sử dụng liên kết varialbes, tùy chọn đầu tiên có vẻ là tốt nhất! – BYS2

+1

@ BYS2: Tôi cũng thích cú pháp này nhất. Không có ý tưởng về hiệu suất. – user272735

0

Biến liên kết có thể được sử dụng trong truy vấn Oracle SQL với mệnh đề "trong".

Làm việc trong 10g; Tôi không biết về các phiên bản khác.

Biến cố định là varchar tối đa 4000 ký tự.

Ví dụ: Biến liên kết chứa danh sách giá trị được phân cách bằng dấu phẩy, ví dụ:

: bindvar = 1,2,3,4,5

select * from mytable 
    where myfield in 
    (
     SELECT regexp_substr(:bindvar,'[^,]+', 1, level) items 
     FROM dual 
     CONNECT BY regexp_substr(:bindvar, '[^,]+', 1, level) is not null 
    ); 

(Same thông tin như tôi được đăng ở đây: How do you specify IN clause in a dynamic query using a variable?)

-2

Chọn Into chức năng chỉ hoạt động cho PL/SQL Block, khi bạn sử dụng Execute ngay lập tức, oracle giải thích v_query_str như là một chuỗi truy vấn SQL để bạn không thể sử dụng vào .will nhận được từ khóa thiếu ngoại lệ. trong ví dụ 2, chúng tôi đang sử dụng bắt đầu kết thúc; do đó, nó đã trở thành pl/sql khối và pháp lý của nó.

Các vấn đề liên quan