2010-01-28 23 views
23

Tôi có bảng này:Cách trả về kết quả/con trỏ từ khối ẩn danh Oracle PL/SQL thực thi SQL động?

ALLITEMS 
--------------- 
ItemId | Areas 
--------------- 
1  | EAST 
2  | EAST 
3  | SOUTH 
4  | WEST 

Các DDL:

drop table allitems; 

Create Table Allitems(ItemId Int,areas Varchar2(20)); 
Insert Into Allitems(Itemid,Areas) Values(1,'east'); 
Insert Into Allitems(ItemId,areas) Values(2,'east'); 
insert into allitems(ItemId,areas) values(3,'south'); 
insert into allitems(ItemId,areas) values(4,'east'); 

Trong MSSQL, để có được một con trỏ từ một SQL năng động, tôi có thể làm:

DECLARE @v_sqlStatement VARCHAR(2000); 
SET @v_Sqlstatement = 'SELECT * FROM ALLITEMS'; 
EXEC (@v_sqlStatement); --returns a resultset/cursor, just like calling SELECT 

Trong Oracle, tôi cần sử dụng một khối PL/SQL:

SET AUTOPRINT ON; 
DECLARE 
V_Sqlstatement Varchar2(2000); 
outputData SYS_REFCURSOR; 
BEGIN 
V_Sqlstatement := 'SELECT * FROM ALLITEMS'; 
OPEN outputData for v_Sqlstatement; 
End; 
--result is : anonymous block completed 

Nhưng tất cả những gì tôi nhận được là "khối ẩn danh đã hoàn tất".
Làm cách nào để đưa nó trở lại con trỏ?
(Tôi biết rằng nếu tôi làm AUTOPRINT, nó sẽ in ra các thông tin trong REFCURSOR (nó không in trong đoạn mã trên, nhưng thats một vấn đề khác))

tôi sẽ gọi này SQL động từ mã (ODBC, C++), và tôi cần nó để trả về một con trỏ.
Làm cách nào để thực hiện việc này? Tôi bối rối.

Trả lời

36

Bạn có thể viết một hàm PL/SQL để trả về con trỏ đó (hoặc bạn có thể đặt chức năng trong một gói nếu bạn có nhiều liên quan đến tiến này):

CREATE OR REPLACE FUNCTION get_allitems 
    RETURN SYS_REFCURSOR 
AS 
    my_cursor SYS_REFCURSOR; 
BEGIN 
    OPEN my_cursor FOR SELECT * FROM allitems; 
    RETURN my_cursor; 
END get_allitems; 

này sẽ trả lại con trỏ.

Đảm bảo không đặt SELECT -Đăng nhập vào các trích dẫn trong PL/SQL khi có thể. Đặt nó trong chuỗi có nghĩa là nó không thể được kiểm tra tại thời gian biên dịch, và rằng nó phải được phân tích cú pháp bất cứ khi nào bạn sử dụng nó.


Nếu bạn thực sự cần phải sử dụng SQL động bạn có thể đặt câu hỏi của bạn trong dấu ngoặc kép duy nhất:

OPEN my_cursor FOR 'SELECT * FROM allitems'; 

Chuỗi này đã được phân tích bất cứ khi nào hàm được gọi, mà thường sẽ chậm hơn và da lỗi trong truy vấn của bạn cho đến khi thời gian chạy.

Hãy chắc chắn để sử dụng bind-biến nếu có thể để tránh hard parses:

OPEN my_cursor FOR 'SELECT * FROM allitems WHERE id = :id' USING my_id; 
+0

Cảm ơn! Tôi sẽ thử cái này. – Liao

+0

@Peter Lang: Bạn sẽ gọi hàm như thế nào trong trường hợp này? – MissPiplup

+0

@MissPiplup: Tôi đã sửa liên kết bị hỏng, điều này có giúp ích cho bạn không? –

8

trong SQL * Plus bạn cũng có thể sử dụng một biến REFCURSOR:

SQL> VARIABLE x REFCURSOR 
SQL> DECLARE 
    2 V_Sqlstatement Varchar2(2000); 
    3 BEGIN 
    4 V_Sqlstatement := 'SELECT * FROM DUAL'; 
    5 OPEN :x for v_Sqlstatement; 
    6 End; 
    7/

ProcÚdure PL/SQL terminÚe avec succÞs. 

SQL> print x; 

D 
- 
X 
+0

Nhưng "print x" có trả lại con trỏ không? Tôi cần gọi khối PL/SQL này từ mã C++ và vì vậy tôi cần nó để trả về một con trỏ. Hoặc là có một cách để truy cập "x" từ mã? – Liao

+0

@Liao: X là con trỏ, bạn sẽ có thể truy cập nó như một biến OUT nếu bạn gọi khối PL/SQL từ C++. 'print' tuy nhiên là một lệnh SQL * Plus và sẽ không hoạt động bên ngoài SQL * Plus. –

1

Bạn sẽ có thể khai báo một con trỏ là biến liên kết (được gọi là tham số trong các DBMS khác)

như Vincent đã viết, bạn có thể làm điều gì đó như sau:

begin 
    open :yourCursor 
    for 'SELECT "'|| :someField ||'" from yourTable where x = :y' 
     using :someFilterValue; 
end; 

Bạn sẽ phải liên kết 3 vars với tập lệnh đó. Một chuỗi đầu vào cho "someField", một giá trị cho "someFilterValue" và một con trỏ cho "yourCursor" mà phải được khai báo là đầu ra var.

Thật không may, tôi không biết bạn sẽ làm điều đó từ C++ như thế nào.(Tuy nhiên, người ta có thể nói may mắn cho tôi. ;-))

Tùy thuộc vào thư viện truy cập bạn sử dụng, nó có thể là một nỗi đau hoàng gia hoặc thẳng về phía trước.

-6

thiết lập này cần phải được thiết lập:

SET SERVEROUTPUT ON 
Các vấn đề liên quan