2009-12-02 30 views
9

tôi có các thủ tục sau:tuổi thọ của bảng temp

CREATE PROCEDURE foo() 
    SELECT * FROM fooBar INTO TEMP tempTable; 

    -- do something with tempTable here 

    DROP TABLE tempTable; 
END PROCEDURE; 

gì xảy ra nếu có một ngoại lệ trước khi DROP TABLE được gọi là? Sẽ tempTable vẫn còn xung quanh sau khi thoát foo?

Nếu vậy, foo có thể thất bại trong lần tiếp theo được gọi, vì tempTable đã tồn tại. Làm thế nào nên được xử lý.

EDIT: Tôi đang sử dụng Informix 11,5

Trả lời

3

cuối cùng tôi đã sử dụng một biến thể của Jonathan và giải pháp RET của:

CREATE PROCEDURE foo() 
    ON EXCEPTION IN (-206) 
    END EXCEPTION WITH RESUME; 

    DROP TABLE tempTable;  

    SELECT * FROM fooBar INTO TEMP tempTable; 

    -- do something with tempTable here 

    DROP TABLE tempTable; 
END PROCEDURE; 
+0

Những gì bạn đã có ở đây - thả bảng nhưng bỏ qua lỗi nếu nó không tồn tại - là một cách tốt để đi. Trong hoàn cảnh bình thường, bảng tạm thời bị thiếu cả trước khi nó chạy và sau khi nó hoàn thành. Nó sẽ có thể tinh chỉnh phạm vi của ngoại lệ, nhưng điều đó sẽ hoạt động tốt. –

+0

Lưu ý rằng Informix hiện đại hỗ trợ các mệnh đề IF EXISTS và IF NOT EXISTS trong các câu lệnh như DROP TABLE. Vì vậy, những ngày này, bạn có thể viết: 'DROP TABLE IF EXISTS tempTable;' sẽ thả bảng nếu nó hiện diện (và bạn có quyền, vv) và không làm gì nếu bảng không tồn tại. –

3

According to the documentation, bảng tạm thời được giảm khi phiên kết thúc.

+0

Tôi đoán, mối quan tâm của tôi là phiên kết thúc khi kết nối được đóng (? Bên phải). Vì vậy, nếu foo được gọi nhiều lần trước khi kết nối được đóng lại và lời gọi đầu tiên cho foo đã ném một ngoại lệ và không dọn sạch bảng tạm thời, thì lệnh gọi hàm foo tiếp theo sẽ thất bại, vì bảng temp đã tồn tại. Thực tiễn tốt nhất để viết mã để bảo vệ điều này là gì. Chúng ta có cần kiểm tra xem bảng tạm thời có tồn tại không và thả nó? – rouble

+0

Tôi đã nhập "kiểm tra xem bảng có tồn tại" mã để kiểm tra trước khi tạo và thả hay không. Informix có cấu trúc bảng tạm thời theo đó một bảng chỉ có thể được xem bởi phiên cụ thể không? SQL Server có chức năng này. – adamcodes

1
SELECT count(*) 
INTO w_count 
FROM sysmaster:systabnames s,sysmaster:systabinfo i 
WHERE i.ti_partnum = s.partnum 
AND sysmaster:BITVAL(i.ti_flags,'0x0020') = 1 
AND s.tabname = 'tempTable' ; 

Nếu w_count bằng 1, hãy xóa bảng trước SELECT ... INTO. Tương tự với DROP TABLE.

2

Có, bảng tạm thời sẽ vẫn tồn tại. Bảng tạm thời theo định nghĩa có một thời gian của phiên tạo ra chúng, trừ khi giảm rõ ràng.

Bảng tạm thời chỉ có thể được xem bởi phiên tạo ra nó và không có trở ngại đối với cùng một quy trình đang được chạy song song bởi nhiều người dùng. Câu trả lời của Adam để kiểm tra sự tồn tại của bảng tạm thời sẽ trả về kết quả khác 0 nếu bất kỳ người dùng nào đang chạy thủ tục. Bạn cần phải kiểm tra xem phiên sở hữu bảng tạm thời có phải là phiên hiện tại không. Cho rằng câu hỏi này nằm trong phạm vi của một thủ tục lưu sẵn, nó có thể đơn giản hơn để thêm một DROP rõ ràng, được bao bọc trong một số xử lý ngoại lệ.

+0

Tôi giả sử bạn có nghĩa là một cái gì đó như thế này: TẠO THỦ TỤC droptempTtable() TRÊN NGOẠI TRỪ (-206) END EXCEPTION; DROP TABLE tempTable; THỦ TỤC END; Có cách nào bạn biết để chỉ định tên bảng, để làm cho thủ tục này chung chung không? – rouble

4

Như những người khác đã nói, các bảng tạm thời kéo dài cho đến khi bạn thả chúng một cách rõ ràng hoặc phiên kết thúc.

Nếu thủ tục được lưu không thành công vì bảng đã tồn tại, SPL tạo ra một ngoại lệ. Bạn có thể xử lý ngoại lệ bằng cách thêm mệnh đề ON EXCEPTION -— nhưng bạn đang nhập một trong các phần baroque của SPL, Ngôn ngữ thủ tục được lưu trữ.

Đây là một phiên bản sửa đổi nhẹ của thủ tục lưu trữ của bạn - một trong đó tạo ra một chia cho số không ngoại lệ (SQL -1202):

CREATE PROCEDURE foo() 
    define i integer; 
    SELECT * FROM 'informix'.systables INTO TEMP tempTable; 

    -- do something with tempTable here 
    let i = 1/0; 

    DROP TABLE tempTable; 
END PROCEDURE; 

execute procedure foo(); 
SQL -1202: An attempt was made to divide by zero. 

execute procedure foo(); 
SQL -958: Temp table temptable already exists in session. 

Điều này cho thấy lần đầu tiên thông qua các mã thực thi SELECT, tạo bảng, và sau đó chạy hôi của phân chia bằng không. Lần thứ hai, mặc dù, SELECT thất bại vì bảng temp đã tồn tại, do đó thông báo lỗi khác nhau.

drop procedure foo; 
CREATE PROCEDURE foo() 
    define i integer; 

    BEGIN 
     ON EXCEPTION 
      DROP TABLE tempTable; 
      SELECT * FROM 'informix'.systables INTO TEMP tempTable; 
     END EXCEPTION WITH RESUME; 
     SELECT * FROM 'informix'.systables INTO TEMP tempTable; 
    END; 

    -- do something with tempTable here 
    let i = 1/0; 

    DROP TABLE tempTable; 
END PROCEDURE; 

Khối BEGIN/END giới hạn xử lý ngoại lệ cho câu lệnh bị bẫy. Nếu không có BEGIN/END, việc xử lý ngoại lệ bao gồm toàn bộ quy trình, phản ứng với sự phân chia bằng lỗi số 0 (và do đó cho phép DROP TABLE hoạt động và quy trình có vẻ chạy thành công).

Lưu ý rằng temptable vẫn còn tồn tại vào thời điểm này:

+ execute procedure foo(); 
SQL -1202: An attempt was made to divide by zero. 
+ execute procedure foo(); 
SQL -1202: An attempt was made to divide by zero. 

Điều này cho thấy các thủ tục không còn thất bại vì bảng tạm thời có mặt.

Bạn có thể giới hạn khối EXCEPTION ON để mã lỗi được lựa chọn (-958 có vẻ hợp lý cho một này) bằng cách:

ON EXCEPTION IN (-958) ... 

Xem Informix Hướng dẫn IBM to SQL: Cú pháp sử dụng, chương 3 'Báo cáo SPL' .

Lưu ý rằng Informix 11,70 thêm 'NẾU EXISTS' và 'NẾU KHÔNG EXISTS' khoản để CREATE và Câu lệnh DROP. Vì vậy, bạn có thể sử dụng các biến đổi DROP TABLE tuyên bố:

DROP TABLE IF EXISTS tempTable; 

Như vậy, với Informix 11,70 hay muộn, cách dễ nhất để viết các thủ tục là:

DROP PROCEDURE IF EXISTS foo; 

CREATE PROCEDURE foo() 
    define i integer; 
    DROP TABLE IF EXISTS tempTable; 

    SELECT * FROM 'informix'.systables INTO TEMP tempTable; 

    -- do something with tempTable here 
    let i = 1/0; 

    DROP TABLE tempTable; -- Still a good idea 
END PROCEDURE; 

Bạn cũng có thể sử dụng điều này, nhưng sau đó bạn có được định nghĩa trước đó của quy trình, bất kể nó là gì, và nó có thể không phải là những gì bạn mong đợi.

CREATE PROCEDURE IF NOT EXISTS foo() 
    define i integer; 
    DROP TABLE IF EXISTS tempTable; 

    SELECT * FROM 'informix'.systables INTO TEMP tempTable; 

    -- do something with tempTable here 
    let i = 1/0; 

    DROP TABLE tempTable; -- Still a good idea 
END PROCEDURE; 
+0

@ Jonathan Tôi đã sử dụng một biến thể của những gì bạn đề xuất ở đây. Tôi đã gửi những gì tôi đã sử dụng làm câu trả lời. Hãy cho tôi biết nếu bạn có bất kỳ ý kiến ​​về spl/sql đó. – rouble

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