2010-03-23 30 views
23

Tôi có một tập lệnh sử dụng gói (PKG_MY_PACKAGE). Tôi sẽ thay đổi một số trường trong truy vấn trong gói đó và sau đó biên dịch lại nó (tôi không thay đổi hoặc biên dịch bất kỳ gói nào khác). Tôi chạy tập lệnh và gặp lỗi giống nhưGói PL/SQL không hợp lệ

 
    ORA-04068: existing state of packages has been discarded 
    ORA-04061: existing state of package body "USER3.PKG_MY_PACKAGE" has been invalidated 
    ORA-04065: not executed, altered or dropped package body "USER3.PKG_MY_PACKAGE" 
    ORA-06508: PL/SQL: could not find program unit being called: "USER3.PKG_MY_PACKAGE" 
    ORA-06512: at line 34 

Tôi chạy lại tập lệnh (không thay đổi bất kỳ thứ gì khác trong hệ thống) và tập lệnh thực thi thành công.

Tôi nghĩ rằng khi tôi biên dịch trước khi tôi thực thi tập lệnh có thể sửa bất kỳ tham chiếu không hợp lệ nào. Đây là bản tái sản xuất 100% và tôi càng sử dụng tập lệnh này càng khó chịu. Điều gì có thể gây ra điều này và điều gì sẽ khắc phục nó?

(oracle 10g, sử dụng PL/SQL Developer 7)

+0

@OMG: Tôi chỉ biên dịch lại phần thân vì đó là tất cả những thay đổi. – FrustratedWithFormsDesigner

+0

Không có lý do gì để bạn sử dụng các biến toàn cục cho việc này - chỉ cần chuyển sang sys_context. Bằng cách này, bạn có thể loại bỏ hoàn toàn các biến toàn cục và làm cho gói của bạn không có trạng thái. –

Trả lời

18

nền

existing state of packages has been discarded phương tiện, mà gói của bạn có một số loại nhà nước.

Điều này là do một biến toàn cục được lưu trữ trong Thân gói của bạn.
Cho đến 11.2.0.2, các hằng số cũng gây ra hành vi này (xem documentation).

Vì gói đã được sử dụng trong phiên của bạn, Oracle giả định rằng trạng thái này có liên quan đến bạn. Một số các biến này có thể có các giá trị khác nhau ngay bây giờ và khi bạn biên dịch lại Nội dung, các giá trị được đặt lại.

Trường hợp ngoại lệ này được ném, để khách hàng của bạn biết rằng họ không thể dựa vào các biến đó nữa.

Solutions

  • Hủy bỏ tất cả các biến toàn cục và hằng (trước 11gR2) từ Body trọn gói nếu có thể
  • Thay thế các biến toàn cầu bằng cách DETERMINISTIC chức năng (theo đề nghị của this answer)
  • Xác định gói với PRAGMA SERIALLY_REUSABLE làm cho Oracle khởi tạo lại các biến toàn cầu với mọi cuộc gọi đến máy chủ.
  • Đóng phiên của bạn và kết nối lại trước khi gọi lại gói.
  • Đặt lại trạng thái một cách thủ công (xem Paul James' answer)
+0

Thật vậy, tôi có một số hình cầu! Tôi sẽ xem nếu tôi có thể tìm thấy một cách xung quanh đó, có thể làm cho họ không globals ... Có cách nào để có giá trị tĩnh cho các thủ tục trong PL/SQL? – FrustratedWithFormsDesigner

+0

Chính xác bạn có ý nghĩa gì bởi "giá trị tĩnh cho các thủ tục"? Các biến toàn cầu này là các biến tĩnh nhiều hơn hoặc ít hơn (mỗi phiên). Cách làm việc đơn giản nhất cho bạn là đặt các biến toàn cục trong phần Header Package thay vì Body - state sẽ không bị vô hiệu hóa nữa khi biên dịch Body. Tại sao bạn cần những globals? –

+0

Chúng giữ các giá trị cấu hình chỉ cần được đặt một lần và thúc đẩy phần còn lại của hệ thống. Tôi không muốn đặt chúng vào tiêu đề vì tôi không muốn bất kỳ mã nào khác có quyền truy cập vào chúng (chúng được chuyển vào một quy trình có liên quan từ tập lệnh). Tôi cho rằng họ có thể được lưu trữ trong một bảng, nhưng có thể có rất nhiều lần đọc trên bảng đó nếu tôi đã làm nó. – FrustratedWithFormsDesigner

20

Nếu bạn đang chạy công cụ trong một kịch bản thử các lệnh trong đó trước khi chạy mã tái biên soạn ..

exec DBMS_SESSION.RESET_PACKAGE 
exec DBMS_SESSION.MODIFY_PACKAGE_STATE(DBMS_SESSION.REINITIALIZE) 

Họ làm những gì tên có thể đề nghị.

+0

Thú vị ... Tôi sẽ phải thử điều này. – FrustratedWithFormsDesigner

+0

Man, tôi ước tôi có thể đánh dấu hai câu trả lời là câu trả lời được chấp nhận. Một trong những nhà phát triển khác ở đây cho biết điều này hoạt động tốt và điều đó có nghĩa là tôi không phải lo lắng về việc viết lại và kiểm tra lại mã. – FrustratedWithFormsDesigner

+0

không hoạt động cho tôi bất kỳ đề xuất nào khác – vakul

0

Vấn đề có thể bạn có thể có là:

  • Gói/thủ tục bạn đang gọi là không hợp lệ (mặc dù nó có thể có tác dụng nếu gọi một cách độc lập) kiểm tra truy vấn này cho dù bạn có một mục của gói hoặc đối tượng của bạn được sử dụng trong gói của bạn trong số này all_objects xem

    select * from all_objects where status = 'INVALID' and owner = 'SCHEMA_NAME';

  • Kiểm tra gói của bạn đang có biến toàn cầu? nếu có thì kiểm tra xem những biến không bị thay đổi bởi bất kỳ phiên khác thích hợp hơn loại bỏ những chức năng toàn cầu biến/sử dụng

  • chạy bên dưới kịch bản để biên dịch tất cả các đối tượng trong schema của bạn

    bắt đầu dbms_utility.compile_schema (' SCHEMA_NAME ', sai); kết thúc;

  • Tùy chọn cuối cùng nếu không có tác vụ nào ở trên xóa tất cả các thủ tục/chức năng khỏi gói của bạn, thêm chức năng mới và cố gắng chạy hàm của bạn từ trình kích hoạt. kiểm tra xem điều này có hiệu quả không thì gói của bạn đang ở trong khóa đặc biệt. Sau khi thêm một hàm mới/proc, trạng thái của nó sẽ hợp lệ trở lại và sau đó bạn có thể thêm tất cả các func/procs thực tế của bạn và loại bỏ hàm/proc mới được bổ sung.
0

Lỗi trên: ORA-06508: PL/SQL: không thể tìm thấy đơn vị chương trình đang được gọi.

được gây ra khi một nỗ lực được thực hiện để gọi một chương trình được lưu trữ mà không thể tìm thấy. Chương trình có thể đã bị xóa hoặc sửa đổi không tương thích hoặc đã biên dịch có lỗi.

Kiểm tra xem tất cả các chương trình được tham chiếu, bao gồm cả các gói phần mềm, tồn tại và tương thích.

Bạn có thể chạy truy vấn này để tìm đối tượng không hợp lệ, có thể gây ra lỗi ORA-06.508:

chọn comp_id, COMP_NAME, phiên bản, trạng thái, namespace, schema từ dba_registry;

+0

Điều này đọc giống như được sao chép trực tiếp từ trang web tài liệu Oracle. – FrustratedWithFormsDesigner

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