Helpex - Trao đổi & giúp đỡ Đăng nhập

Đặt và sử dụng cờ tổng hợp có điều kiện của riêng bạn

Phan Trúc Ly
· 17:00 21/05/2019
01:39:52 16/06/2021

Đặt và sử dụng cờ tổng hợp có điều kiện của riêng bạn

Bài đăng này là bài thứ tư trong loạt bài của tôi về biên dịch có điều kiện. Bạn sẽ tìm thấy các liên kết đến toàn bộ loạt bài ở dưới cùng.

Trong bài đăng này, tôi khám phá cách đặt và sử dụng cờ biên dịch có điều kiện (còn được gọi là lệnh truy vấn và dưới đây được gọi là ccflags ) được sử dụng trong các câu lệnh $ IF và kiểm soát mã nào sẽ được bao gồm hoặc loại trừ khi quá trình biên dịch xảy ra.

Về lý thuyết, bạn không cần đến ccflags. Bạn chỉ có thể tạo một gói với các hằng số tĩnh, như DBMS_DB_VERSION , rồi tham chiếu các hằng số đó trong các câu lệnh $ IF. Điều đó có ý nghĩa khi nhiều đơn vị biên dịch khác nhau (gói, thủ tục, trình kích hoạt, chức năng, kiểu đối tượng) cần được kiểm soát nhất quán bởi cùng một cài đặt. Với cách tiếp cận gói, khi bạn thay đổi một giá trị cho hằng số, các đơn vị chương trình phụ thuộc sẽ bị vô hiệu và khi biên dịch lại, sẽ được biên dịch với các giá trị mới.

Mặt khác, nếu bạn muốn thêm logic biên dịch có điều kiện vào một đơn vị hoặc một số ít, thì bạn có thể thấy một gói dành riêng cho mục đích này là hơi quá. Đối với tình huống này, bạn có thể cân nhắc sử dụng lệnh truy vấn thay thế. Bạn biết rằng bạn đang xem xét ccflag hoặc chỉ thị truy vấn khi bạn nhìn thấy một số nhận dạng có tiền tố là "$$".

Một lệnh truy vấn nhận được giá trị của nó từ môi trường biên dịch, theo ba cách khác nhau:

  1. từ một tham số biên dịch PL / SQL
  2. từ một ccflag được xác định trước
  3. từ ccflag do người dùng xác định

Tham số biên dịch

PL / SQL cung cấp các tham số biên dịch sau dưới dạng chỉ thị truy vấn:

$$ PLSCOPE_SETTINGS - cài đặt hiện tại cho PL / Phạm vi cho một đơn vị chương trình

$$ PLSQL_CCFLAGS - cài đặt hiện tại cho ccflags do người dùng xác định cho một đơn vị chương trình

$$ PLSQL_CODE_TYPE - loại mã, NATIVE hoặc INTERPRETED

$$ PLSQL_OPTIMIZE_LEVEL - mức tối ưu hóa được sử dụng để biên dịch đơn vị chương trình

$$ PLSQL_WARNINGS - cài đặt cảnh báo thời gian biên dịch cho đơn vị chương trình

$$ NLS_LENGTH_SEMANTICS - Ngữ nghĩa độ dài NLS cho đơn vị chương trình

Đây là một quy trình bạn có thể sử dụng để hiển thị các giá trị hiện tại cho các tham số này trong phiên của bạn (có sẵn để tải xuống trong tập lệnh LiveSQL này ):

BEGIN
  DBMS_OUTPUT.PUT_LINE('$$PLSCOPE_SETTINGS = '     || $$PLSCOPE_SETTINGS);
  DBMS_OUTPUT.PUT_LINE('$$PLSQL_CCFLAGS = '        || $$PLSQL_CCFLAGS);
  DBMS_OUTPUT.PUT_LINE('$$PLSQL_CODE_TYPE = '      || $$PLSQL_CODE_TYPE);
  DBMS_OUTPUT.PUT_LINE('$$PLSQL_OPTIMIZE_LEVEL = ' || $$PLSQL_OPTIMIZE_LEVEL);
  DBMS_OUTPUT.PUT_LINE('$$PLSQL_WARNINGS = '       || $$PLSQL_WARNINGS);
  DBMS_OUTPUT.PUT_LINE('$$NLS_LENGTH_SEMANTICS = ' || $$NLS_LENGTH_SEMANTICS);
END;

Thông tin tương tự này được lưu trữ liên tục trong cơ sở dữ liệu cho mọi đơn vị chương trình và có sẵn thông qua chế độ xem USER / ALL_PLSQL_OBJECT_SETTINGS, như trong:

SELECT *
  FROM all_plsql_object_settings
 WHERE name = 'PROGRAM_NAME'

Thẻ CCF được xác định trước

Kể từ Oracle Database 19c, ccflags được tự động xác định cho bất kỳ đơn vị chương trình nào là:

$$ PLSQL_LINE - Một ký tự PLS_INTEGER có giá trị là số dòng nguồn mà trên đó chỉ thị xuất hiện trong đơn vị PL / SQL hiện tại.

$$ PLSQL_UNIT - Một ký tự VARCHAR2 chứa tên của đơn vị PL / SQL hiện tại. Nếu đơn vị PL / SQL hiện tại là một khối ẩn danh thì $$ PLSQL_UNIT chứa giá trị NULL.

$$ PLSQL_UNIT_OWNER - Một ký tự VARCHAR2 chứa tên của chủ sở hữu của đơn vị PL / SQL hiện tại. Nếu đơn vị PL / SQL hiện tại là một khối ẩn danh thì $$ PLSQL_UNIT_OWNER chứa giá trị NULL.

$$ PLSQL_UNIT_TYPE - Một ký tự VARCHAR2 chứa loại đơn vị PL / SQL hiện tại-ANONYMOUS BLOCK, FUNCTION, PACKAGE, PACKAGE BODY, PROCEDURE, TRIGGER, TYPE hoặc TYPE BODY. Bên trong khối ẩn danh hoặc trình kích hoạt không phải DML, $$ PLSQL_UNIT_TYPE có giá trị ANONYMOUS BLOCK.

Tuy nhiên, bạn có thể thất vọng về cách bạn có thể sử dụng những lá cờ này. Các chỉ thị chọn lọc ($ IF) chỉ được chứa các biểu thức tĩnh, có nghĩa là chúng được giải quyết tại thời điểm biên dịch, có nghĩa là trong thế giới Cơ sở dữ liệu Oracle, bạn chỉ có thể làm việc với các giá trị số nguyên và Boolean.

Vì vậy, mã này sẽ biên dịch:

PROCEDURE test_cc
IS
BEGIN
   $IF $$PLSQL_UNIT IS NULL $THEN
   -- Include this line
   $END
   NULL;
END;

nhưng điều này khiến tôi đau đầu:

PROCEDURE test_cc
IS
BEGIN
   $IF $$PLSQL_UNIT = 'TEST_CC' $THEN
   -- Include this line
   $END
   NULL;
END;

PLS-00174: a static boolean expression must be used

Do đó, các cờ được xác định trước này chủ yếu được sử dụng cho các mục đích theo dõi và ghi nhật ký, như trong:

CREATE OR REPLACE PROCEDURE using_predefined_ccflags
   AUTHID DEFINER
IS
   myvar   INTEGER := 100;
BEGIN
   DBMS_OUTPUT.put_line (
      'On line ' || $$plsql_line || ' value of myar is ' || myvar);
   RAISE PROGRAM_ERROR;      
EXCEPTION
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line ('Failure in program unit ' ||
            $$plsql_unit_owner || '.' ||
            $$plsql_unit_type || '.' ||
            $$plsql_unit);
END;
/

BEGIN
   using_predefined_ccflags;
END;
/

Procedure created.
Statement processed.
On line 7 value of myar is 100
Failure in program unit SCOTT.PROCEDURE.USING_PREDEFINED_CCFLAGS

Thẻ CCFL do người dùng xác định

Các ccflags do người dùng xác định được xác định bằng cách đặt tham số PLSQL_CCFlags trước khi đơn vị chương trình của bạn được biên dịch. Bạn có thể đặt ccflags theo cách này ở cấp đơn vị phiên hoặc chương trình. Dưới đây là một số ví dụ:

ALTER SESSION SET plsql_ccflags = 'Flag1:10, Flag2:true'
/

ALTER PROCEDURE myproc
COMPILE SET PLSQL_CCFlags = 'Flag1:10, Flag2:true' REUSE SETTINGS
/

Vì chúng do người dùng xác định, bạn có thể sử dụng chúng cho bất cứ điều gì. Bạn có thể bật và tắt theo dõi hoặc số lượng theo dõi. Bạn có thể bao gồm hoặc loại trừ các đoạn mã tùy thuộc vào các tính năng mà người dùng của bạn đã trả tiền. Bạn có thể hiển thị các chương trình con được đóng gói riêng trong đặc tả gói để bạn có thể kiểm tra chúng trực tiếp và sau đó đảm bảo rằng chúng được ẩn trong quá trình sản xuất.

Đây là một ví dụ về trường hợp sử dụng đó (cũng trong LiveSQL ):

ALTER SESSION SET PLSQL_CCFLAGS = 'show_private_joke_programs:TRUE'
/

CREATE OR REPLACE PACKAGE sense_of_humor
IS
   PROCEDURE calc_how_funny (
      joke_in               IN       VARCHAR2
    , funny_rating_out      OUT      NUMBER
    , appropriate_age_out   OUT      NUMBER
   );
$IF $$show_private_joke_programs $THEN
   FUNCTION humor_level ( joke_in IN VARCHAR2 )
      RETURN NUMBER;
            
    FUNCTION maturity_level ( joke_in IN VARCHAR2 )
      RETURN NUMBER;
$END         
END;
/

CREATE OR REPLACE PACKAGE BODY sense_of_humor
IS
   FUNCTION humor_level ( joke_in IN VARCHAR2 )
      RETURN NUMBER
   IS
   BEGIN
      -- Some really interesting code here...
      RETURN NULL;
   END humor_level;

   FUNCTION maturity_level ( joke_in IN VARCHAR2 )
      RETURN NUMBER
   IS
   BEGIN
      -- Some really interesting code here...
      RETURN NULL;
   END maturity_level;

   PROCEDURE calc_how_funny (
      joke_in               IN       VARCHAR2
    , funny_rating_out      OUT      NUMBER
    , appropriate_age_out   OUT      NUMBER
   )
   IS
   BEGIN
      funny_rating_out := humor_level ( joke_in );
      appropriate_age_out := maturity_level ( joke_in );
   END calc_how_funny;
END;
/

Mẹo sử dụng CCFlags

Đừng giả định bất cứ điều gì

Ý tôi là: đừng cho rằng ccflags do người dùng xác định đã được đặt trước khi biên dịch để sử dụng trong sản xuất .

Nếu một ccflag chưa được xác định bằng lệnh ALTER, nó được đánh giá là NULL.

Vì vậy, hành vi của mã của bạn trong sản xuất, bất cứ khi nào có thể, được xác định bởi giá trị của tất cả các ccflags của bạn được đặt thành NULL. Bằng cách đó, nếu vì bất kỳ lý do gì mà mã được biên dịch mà không chạy câu lệnh ALTER thích hợp, bạn sẽ không gặp phải một mớ hỗn độn lớn.

Giữ cài đặt CCFlag bằng mã

Một cách để tránh sự cố được mô tả ở trên là giữ tất cả các cài đặt ccflag cần thiết cho một đơn vị chương trình cụ thể trong tệp cho chính đơn vị đó. Sau đó, bất cứ khi nào bạn cần biên dịch đơn vị chương trình đó, ccflags được đặt trước, và sau đó quá trình biên dịch diễn ra.

Kiểm tra thẻ CCFlags không xác định

Sử dụng tính năng cảnh báo thời gian biên dịch của PL / SQL để tiết lộ bất kỳ ccflags nào chưa được đặt tại thời điểm biên dịch. Đây là một ví dụ:

ALTER SESSION SET plsql_warnings = 'ENABLE:ALL'
/

CREATE OR REPLACE PACKAGE sense_of_humor AUTHID DEFINER
IS
   PROCEDURE calc_how_funny (
      joke_in               IN       VARCHAR2
    , funny_rating_out      OUT      NUMBER
    , appropriate_age_out   OUT      NUMBER
   );
$IF $$show_private_joke_programs $THEN
   FUNCTION humor_level ( joke_in IN VARCHAR2 )
      RETURN NUMBER;
$END         
END;
/

PLW-06003: unknown inquiry directive '$$SHOW_PRIVATE_JOKE_PROGRAMS'

Loạt bài tổng hợp có điều kiện

1. Giới thiệu về biên dịch có điều kiện
2. Xem mã được biên dịch có điều kiện: cái gì sẽ được chạy?
3. Viết mã để hỗ trợ nhiều phiên bản của Cơ sở dữ liệu Oracle
4. Thiết lập và sử dụng cờ biên dịch có điều kiện của riêng bạn

4 hữu ích 0 bình luận 5.5k xem chia sẻ

Có thể bạn quan tâm