PL/SQL的隐藏功能

Ada*_*ter 27 sql oracle plsql

在光"的......隐藏功能"系列的问题,有什么鲜为人知的PL/SQL的功能已经成为你有用吗?

编辑:特定于PL/SQL的功能优先于Oracle SQL语法的功能.但是,因为PL/SQL可以使用大多数Oracle的SQL结构,所以如果它们使PL/SQL中的编程更容易,则可以包含它们.

Jef*_*emp 25

您可以覆盖变量,可以命名匿名块,您仍然可以通过名称引用重写的变量:

PROCEDURE myproc IS
   n NUMBER;
BEGIN
   n := 1;
   <<anon>>
   DECLARE
      n NUMBER;
   BEGIN
      n := 2;
      dbms_output.put_line('n=' || n);
      dbms_output.put_line('anon.n=' || anon.n);
      dbms_output.put_line('myproc.n=' || myproc.n);
   END anon;
END myproc;
Run Code Online (Sandbox Code Playgroud)

  • 我甚至不知道块可以有标签!很有用! (2认同)

die*_*ikh 17

除了整数之外,您还可以通过其他类型索引pl/sql表.这样您就可以创建类似结构的"字典",这可以使您的代码更容易阅读:

例:

DECLARE
  TYPE dictionary IS TABLE OF VARCHAR2(200) INDEX BY VARCHAR2(100);
  dict dictionary;
BEGIN
  dict('NAME') := 'John Doe';
  dict('CITY') := 'New York';

  dbms_output.put_line('Name:' || dict('NAME'));
END;
Run Code Online (Sandbox Code Playgroud)

  • 再一次,我不知道你能做的另一件事!很有用! (2认同)

小智 15

真正隐藏的oracle函数是OVERLAPS函数,但使用任何不受支持的功能可能不是很明智.

select 'yes' from dual where (sysdate-5,sysdate) overlaps (sysdate-2,sysdate-1);
Run Code Online (Sandbox Code Playgroud)


Ada*_*ter 13

我获得巨大成功的一个鲜为人知的特性是能够使用声明为其的变量插入表中%ROWTYPE.例如:

CREATE TABLE CUSTOMERS (
    id NUMBER,
    name VARCHAR2(100),
    birth DATE,
    death DATE
)

PROCEDURE insert_customer IS
    customer CUSTOMERS%ROWTYPE;
BEGIN
    customer.id := 45;
    customer.name := 'John Smith';
    customer.birth := TO_DATE('1978/04/03', 'YYYY/MM/DD');

    INSERT INTO CUSTOMERS VALUES customer;
END;
Run Code Online (Sandbox Code Playgroud)

虽然它咀嚼了更多的重做表空间,但它确实使得插入数据(尤其是更大的表格)更加清晰.它还避免了存储要插入的每个列的值所需的众多变量.


Ada*_*ter 12

程序和功能可以在DECLARE块内定义:

DECLARE

    PROCEDURE print(text VARCHAR2) IS
    BEGIN
        DBMS_OUTPUT.put_line(text);
    END;

BEGIN

    print('Yay!');
    print('Woo hoo!');

END;
Run Code Online (Sandbox Code Playgroud)

这对于创建独立脚本非常方便.

  • 您还可以嵌套过程和函数,这在您需要将大型过程分解为几个较小过程而不传递大量参数时尤其有用. (3认同)

Ult*_*mit 12

您是否知道使用选项SAMPLE(K),您只能选择由最多K%的Oracle表组成的样本?

SELECT *
  FROM MASSIVE_TABLE SAMPLE (5);
Run Code Online (Sandbox Code Playgroud)

前一个语句检索由称为MASSIVE_TABLE的大量表中存储的最多5%记录组成的随机集.

  • 这不是PL/SQL. (6认同)

Jon*_*han 10

也许不够隐藏,但我喜欢允许make upserts(插入或更新)的Merge语句

MERGE <hint> INTO <table_name>
USING <table_view_or_query>
ON (<condition>)
WHEN MATCHED THEN <update_clause>
DELETE <where_clause>
WHEN NOT MATCHED THEN <insert_clause>
[LOG ERRORS <log_errors_clause> <reject limit <integer | unlimited>];
Run Code Online (Sandbox Code Playgroud)

  • MERGE不是PL/SQL(3GL),而是Oracle SQL语句. (6认同)

Ton*_*ews 10

我对Oracle中隐藏功能的回答与此相关:

由于Apex现在是每个Oracle数据库的一部分,因此即使您不使用Apex,这些Apex实用程序功能也很有用:

SQL> declare
  2    v_array apex_application_global.vc_arr2;
  3    v_string varchar2(2000);
  4  begin
  5  
  6    -- Convert delimited string to array
  7    v_array := apex_util.string_to_table('alpha,beta,gamma,delta', ',');
  8    for i in 1..v_array.count
  9    loop
 10      dbms_output.put_line(v_array(i));
 11    end loop;
 12  
 13    -- Convert array to delimited string
 14    v_string := apex_util.table_to_string(v_array,'|');
 15    dbms_output.put_line(v_string);
 16  end;
 17  /
alpha
beta
gamma
delta
alpha|beta|gamma|delta

PL/SQL procedure successfully completed.
Run Code Online (Sandbox Code Playgroud)


Rob*_*ebe 7

这是一个PL/SQL程序构造,我使用了很多(Steven Feuerstein和Chen Shapira).用于链接的关联数组,但它不预先加载所有数据,但如果需要则从数据库获取数据并将其放入关联数组中.

create or replace
PACKAGE justonce
IS
  FUNCTION hair (code_in IN hairstyles.code%TYPE)
    RETURN hairstyles%ROWTYPE;
  TYPE hair_t IS TABLE OF hairstyles%ROWTYPE
    INDEX BY BINARY_INTEGER;
  hairs          hair_t;
END justonce;

create or replace 
PACKAGE BODY justonce
IS
  FUNCTION hair (code_in IN hairstyles.code%TYPE) RETURN hairstyles%ROWTYPE
  IS
    return_value   hairstyles%ROWTYPE;
    FUNCTION hair_from_database RETURN hairstyles%ROWTYPE
    IS
      CURSOR hair_cur IS
      SELECT * FROM hairstyles WHERE code = code_in;
    BEGIN
      OPEN hair_cur;
      FETCH hair_cur INTO return_value;
      CLOSE hair_cur;
      RETURN return_value;
    END hair_from_database;
  BEGIN
    IF NOT (hairs.exists(code_in))
    THEN
      dbms_output.put_line('Get record from database');
      hairs (code_in) := hair_from_database;
    END IF;
    RETURN hairs (code_in);
  END hair;
END justonce;
Run Code Online (Sandbox Code Playgroud)

测试一下:

declare
    h hairstyles%ROWTYPE;
begin
   for i in 1000..1004
   loop
      h := justonce.hair(i);
      dbms_output.put_line(h.description);
   end loop;
   for i in 1000..1004
   loop
      h := justonce.hair(i);
      dbms_output.put_line(h.description||' '||h.price);
   end loop;

end;
/

Get record from database
CREWCUT
Get record from database
BOB
Get record from database
SHAG
Get record from database
BOUFFANT
Get record from database
PAGEBOY
CREWCUT 10
BOB 20
SHAG 21
BOUFFANT 11
PAGEBOY 44
Run Code Online (Sandbox Code Playgroud)


And*_*int 6

  1. 未记录的函数:dbms_system.ksdwrt(写入警报/跟踪文件)
  2. DBMS_SQL包(作为其使用示例,请参阅此问题
  3. AUTHID CURRENT_USER子句
  4. 条件编译