Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Sử dụng Oracle EXPAND_SQL_TEXT

Các bảng cơ sở dữ liệu không phải là các thực thể tĩnh; bên cạnh các sự kiện chèn / cập nhật / xóa thông thường, DDL không thường xuyên có thể được thực hiện để thêm cột, bỏ cột hoặc thêm các ràng buộc hoặc chỉ mục cần thiết. Hai mục đầu tiên có thể tạo ra các vấn đề với các thủ tục, gói, hàm được lưu trữ và có thể kích hoạt bằng cách thay đổi số cột cần được xử lý khi các biến rõ ràng được sử dụng. Nếu người lập trình đã sử dụng một biến bản ghi (như hình bên dưới) thì không có vấn đề gì có thể xảy ra:

SPLEEBO @ gwankus > 
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > -- Code to display all employee information
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > -- This should succeed
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > declare
  2  	     cursor get_emp_info is
  3  	     select * From emp;
  4  begin
  5  	     for emp_rec in get_emp_info loop
  6  		     dbms_output.put_line(emp_rec.empno||' '||emp_rec.ename||' '||emp_rec.job||' '||emp_rec.mgr||' '||emp_rec.hiredate||' '||emp_rec.sal||' '||emp_rec.comm||' '||emp_rec.deptno);
  7  	     end loop;
  8  end;
  9  /
7369 SMITH CLERK 7902 17-DEC-80 800  20                                         
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30                                  
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30                                   
7566 JONES MANAGER 7839 02-APR-81 2975  20                                      
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30                                
7698 BLAKE MANAGER 7839 01-MAY-81 2850  30                                      
7782 CLARK MANAGER 7839 09-JUN-81 2450  10                                      
7788 SPLEEBO ANALYST 7566 09-DEC-82 3000  20                                      
7839 KING PRESIDENT  17-NOV-81 5000  10                                         
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30                                   
...
6100 MILLER CLERK 7782 23-SEP-97 1300  10                                       
SPLEEBO @ gwankus > 

Nếu các biến rõ ràng được sử dụng, thì có khả năng mã sẽ không thành công do thay đổi. Bạn có thể bối rối khi thấy những điều sau trong một thông báo lỗi:

PLS-00394: wrong number of values in the INTO list of a FETCH statement 

Tất nhiên việc điều tra sẽ tiết lộ một câu lệnh ‘thay đổi bảng…’ đã được thực hiện trước khi xảy ra lỗi hoặc một mô tả trên bảng bị ảnh hưởng sẽ báo cáo một số cột khác với số cột hiện có khi mã được viết ban đầu. Một khi sự thật này được biết, việc khắc phục sự cố phụ thuộc vào nhà phát triển đã viết ra nó. Họ sẽ có các lựa chọn về cách tiếp tục thực hiện những thay đổi như vậy.

Xem xét một ví dụ sử dụng các biến được mã hóa rõ ràng và một cột được thêm vào, hãy khám phá bằng cách sử dụng quy trình từ gói DBMS_UTILITY, EXPAND_SQL_TEXT, để tạo danh sách cột hoàn chỉnh từ bảng đã sửa đổi để sử dụng làm tham chiếu cho các thay đổi mã. Đầu tiên, mã gốc và lỗi mà nó tạo ra:

SPLEEBO @ gwankus > 
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > -- Code to display all employee information
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > -- Fails because not enough variables are declared
SPLEEBO @ gwankus > -- and populated
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > declare
  2  	     v_empno emp.empno%type;
  3  	     v_ename emp.ename%type;
  4  	     v_job   emp.job%type;
  5  	     v_mgr   emp.mgr%type;
  6  	     v_hiredate      emp.hiredate%type;
  7  	     v_sal   emp.sal%type;
  8  	     v_comm  emp.comm%type;
  9  	     v_deptno	     emp.deptno%type;
 10  
 11  	     cursor get_emp_info is
 12  	     select * From emp;
 13  begin
 14  	     open get_emp_info;
 15  	     loop
 16  		     fetch get_emp_info into v_empno, v_ename, v_job, v_mgr, v_hiredate, v_sal, v_comm, v_deptno;
 17  		     exit when get_emp_info%notfound;
 18  		     dbms_output.put_line(v_empno||' '||v_ename||' '||v_job||' '||v_mgr||' '||v_hiredate||'  '||v_sal||' '||v_comm||' '||v_deptno);
 19  	     end loop;
 20  end;
 21  /
		fetch get_emp_info into v_empno, v_ename, v_job, v_mgr, v_hiredate, v_sal, v_comm, v_deptno;
		*
ERROR at line 16:
ORA-06550: line 16, column 3: 
PLS-00394: wrong number of values in the INTO list of a FETCH statement 
ORA-06550: line 16, column 3: 
PL/SQL: SQL Statement ignored 


SPLEEBO @ gwankus > 
SPLEEBO @ gwankus > 

Tạo một bản sao của mã gốc (nếu cần) và sử dụng DBMS_UTILITY.EXPAND_SQL_TEXT để tạo, dưới dạng nhận xét, kết quả mở rộng của truy vấn ‘select * from…” dựa vào bảng đã sửa đổi. Thủ tục yêu cầu một biến CLOB được khai báo để giữ kết quả của lệnh gọi thủ tục và cũng yêu cầu truy vấn ‘select *’ cụ thể để hoạt động. Đoạn mã được hiển thị bên dưới tạo ra kết quả này dưới dạng nhận xét và có thể được sử dụng lại bằng cách chỉnh sửa tên bảng trong truy vấn được cung cấp:

SPLEEBO @ gwankus > --
SPLEEBO @ gwankus >-- Expand the 'select *' query to see all
SPLEEBO @ gwankus >-- of the returned columns
SPLEEBO @ gwankus >--
SPLEEBO @ gwankus >-- Add the output to the failing script
SPLEEBO @ gwankus >-- to facilitate corrective edits
SPLEEBO @ gwankus >--
SPLEEBO @ gwankus >spool new_query.sql
SPLEEBO @ gwankus >declare
  2    l_clob clob;
  3  begin
  4    dbms_utility.expand_sql_text (
  5      input_sql_text  => 'select * from emp',
  6      output_sql_text => l_clob
  7    );
  8
  9    dbms_output.put_line('/*');
 10    dbms_output.put_line(lower(l_clob));
 11    dbms_output.put_line('*/');
 12  end;
 13  /

/*                                                                              
select "a1"."empno" "empno","a1"."ename" "ename","a1"."job" "job","a1"."mgr"    
"mgr","a1"."hiredate" "hiredate","a1"."sal" "sal","a1"."comm"                   
"comm","a1"."deptno" "deptno","a1"."term_dt" "term_dt" from "scott"."emp" "a1"  
*/                                                                              

PL/SQL procedure successfully completed.

SPLEEBO @ gwankus > spool off

Tạo một bản sao làm việc và nối đầu ra của truy vấn trên vào nó. Sau đó, mở tệp đã sửa đổi trong trình chỉnh sửa bạn chọn để thực hiện các thay đổi cần thiết:

SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > -- Copy the original script to preserve code
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > !cp emp_info_pl_orig.sql emp_info_pl.sql

SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > -- Add the output generated above as a comment
SPLEEBO @ gwankus > -- for reference purposes
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > !cat new_query.sql >> emp_info_pl.sql

SPLEEBO @ gwankus > 
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > -- Edit the script copy to fix the issue by
SPLEEBO @ gwankus > -- adding the necessary variable declaration
SPLEEBO @ gwankus > -- and editing the code to populate it
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > !vi emp_info_pl.sql

declare
        v_empno emp.empno%type;
        v_ename emp.ename%type;
        v_job   emp.job%type;
        v_mgr   emp.mgr%type;
        v_hiredate      emp.hiredate%type;
        v_sal   emp.sal%type;
        v_comm  emp.comm%type;
        v_deptno        emp.deptno%type;
        v_term_dt        emp.term_dt%type;

        cursor get_emp_info is
        select * From emp;
begin
        open get_emp_info;
        loop
                fetch get_emp_info into v_empno, v_ename, v_job, v_mgr, v_hiredate, v_sal, v_comm, v_deptno, v_term_dt;
                exit when get_emp_info%notfound;
                dbms_output.put_line(v_empno||' '||v_ename||' '||v_job||' '||v_mgr||' '||v_hiredate||' '||v_sal||' 
'||v_comm||' '||v_deptno||' '||v_term_dt); end loop; end; / /* select "a1"."empno" "empno","a1"."ename" "ename","a1"."job" "job","a1"."mgr" "mgr","a1"."hiredate" "hiredate","a1"."sal" "sal","a1"."comm" "comm","a1"."deptno" "deptno","a1"."term_dt" "term_dt" from "scott"."emp" "a1" */

Kiểm tra các thay đổi để đảm bảo mọi thứ hoạt động như mong đợi:

SPLEEBO @ gwankus > 
SPLEEBO @ gwankus > set head on feedback on pagesize 60
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > -- Run modified code
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > -- The anonymous block now completes
SPLEEBO @ gwankus > -- without error
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > @emp_info_pl
SPLEEBO @ gwankus > declare
  2  	     v_empno emp.empno%type;
  3  	     v_ename emp.ename%type;
  4  	     v_job   emp.job%type;
  5  	     v_mgr   emp.mgr%type;
  6  	     v_hiredate      emp.hiredate%type;
  7  	     v_sal   emp.sal%type;
  8  	     v_comm  emp.comm%type;
  9  	     v_deptno	     emp.deptno%type;
 10  	     v_term_dt	      emp.term_dt%type;
 11  
 12  	     cursor get_emp_info is
 13  	     select * From emp;
 14  begin
 15  	     open get_emp_info;
 16  	     loop
 17  		     fetch get_emp_info into v_empno, v_ename, v_job, v_mgr, v_hiredate, v_sal, v_comm, v_deptno, v_term_dt;
 18  		     exit when get_emp_info%notfound;
 19  		     dbms_output.put_line(v_empno||' '||v_ename||' '||v_job||' '||v_mgr||' '||v_hiredate||' '||v_sal||' '||v_comm||' '||v_deptno||' '||v_term_dt);
 20  	     end loop;
 21  end;
 22  /
7369 SMITH CLERK 7902 17-DEC-80 800  20 31-DEC-99                               
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 31-DEC-99                        
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 31-DEC-99                         
7566 JONES MANAGER 7839 02-APR-81 2975  20 31-DEC-99                            
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 31-DEC-99                      
7698 BLAKE MANAGER 7839 01-MAY-81 2850  30 31-DEC-99                            
7782 CLARK MANAGER 7839 09-JUN-81 2450  10 31-DEC-99                            
7788 SPLEEBO ANALYST 7566 09-DEC-82 3000  20 31-DEC-99                            
7839 KING PRESIDENT  17-NOV-81 5000  10 31-DEC-99                               
...
6100 MILLER CLERK 7782 23-SEP-97 1300  10 31-DEC-99                             

PL/SQL procedure successfully completed.

SPLEEBO @ gwankus > --

Kỹ thuật tương tự này có thể được sử dụng trên các bảng có số lượng cột tương đối lớn:

SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > -- Let's take another example
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > -- Create a table with 21 columns
SPLEEBO @ gwankus > -- and populate it
SPLEEBO @ gwankus > --
SPLEEBO @ gwankus > @lotsa_cols
SPLEEBO @ gwankus > create table lotsacols(
  2  a1      number,
  3  a2      number,
  4  a3      number,
  5  a4      number,
  6  a5      number,
  7  a6      number,
  8  a7      number,
  9  a8      number,
 10  a9      number,
 11  a10     number,
 12  a11     number,
 13  a12     number,
 14  a13     number,
 15  a14     number,
 16  a15     number,
 17  a16     number,
 18  a17     number,
 19  a18     number,
 20  a19     number,
 21  a20     number,
 22  a21     number);

Table created.

SPLEEBO @ gwankus > 
SPLEEBO @ gwankus > begin
  2  	     for z in 1..1000 loop
  3  		     insert into lotsacols(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21)
  4  		     values(mod(z,3)+1,mod(z,13)+1,mod(z,21)+1,mod(z,34)+1,mod(z,47)+1,mod(z,53)+1,
mod(z,67)+1,mod(z,79)+1,mod(z,81)+1,mod(z,97)+1,mod(z,3)+1,mod(z,7)+1,mod(z,6)+1,mod(z,2)+1,
mod(z,9)+1,mod(z,8)+1,mod(z,101)+1,mod(z,407)+1,mod(z,313)+1,mod(z,271)+1,mod(z,133)+1); 5 end loop; 6 7 commit; 8 end; 9 / PL/SQL procedure successfully completed. SPLEEBO @ gwankus > SPLEEBO @ gwankus > SPLEEBO @ gwankus > -- SPLEEBO @ gwankus > -- Rather than do a DESC on the table SPLEEBO @ gwankus > -- use expand_sql_text to generate the SPLEEBO @ gwankus > -- column list and spool it to a file for SPLEEBO @ gwankus > -- later use SPLEEBO @ gwankus > -- SPLEEBO @ gwankus > -- Edit that file to create a working block SPLEEBO @ gwankus > -- of PL/SQL to generate results from the SPLEEBO @ gwankus > -- table data SPLEEBO @ gwankus > -- /* select "a1"."a1" "a1","a1"."a2" "a2","a1"."a3" "a3","a1"."a4" "a4","a1"."a5" "a5","a1"."a6" "a6","a1"."a7" "a7","a1"."a8" "a8","a1"."a9" "a9","a1"."a10" "a10","a1"."a11" "a11","a1"."a12" "a12","a1"."a13" "a13","a1"."a14" "a14","a1"."a15" "a15","a1"."a16" "a16","a1"."a17" "a17","a1"."a18" "a18","a1"."a19" "a19","a1"."a20" "a20","a1"."a21" "a21" from "scott"."lotsacols" "a1" */ declare cursor get_lotsa is select * From lotsacols; begin dbms_output.put_line('Your lucky LOTTO numbers are: '); for lotsa in get_lotsa loop dbms_output.put_line(lotsa.a1||' '||lotsa.a6||' '||lotsa.a7||' '||lotsa.a13||' '||lotsa.a17||' '||lotsa.a20); end loop; end; / SPLEEBO @ gwankus > -- SPLEEBO @ gwankus > -- Execute the code SPLEEBO @ gwankus > -- Your lucky LOTTO numbers are: 2 50 8 5 7 209 3 51 9 6 8 210 1 52 10 1 9 211 ... 2 53 11 2 10 212 1 32 51 1 14 179 2 33 52 2 15 180 3 34 53 3 16 181 PL/SQL procedure successfully completed.

Sử dụng EXPAND_SQL_TEXT có thể dễ dàng hơn so với việc tạo danh sách bảng bằng DESC và lưu trữ kết quả vì nó tạo ra một tệp nhỏ hơn có thể dễ dàng được kết hợp vào một quy trình thay đổi. Vì văn bản SQL mở rộng được tạo dưới dạng nhận xét, nó có thể vẫn còn sau khi hoàn thành chỉnh sửa trong trường hợp cần hoặc muốn có thêm các thay đổi mã.

Lựa chọn là của nhà phát triển, nhưng chắc chắn có vẻ dễ dàng hơn khi để Oracle tạo đầu ra có thể sử dụng theo cách hơi tự động để tạo điều kiện chỉnh sửa mã. Cuối cùng, bất cứ điều gì mà nhà phát triển cảm thấy thoải mái nhất là điều quan trọng nhất. Tuy nhiên, bạn nên điều tra bằng EXPAND_SQL_TEXT để đưa thông tin tham chiếu đó vào tập lệnh đang được chỉnh sửa và có thể tránh bị lạc giữa hai màn hình mã. Điều đó có thể tiết kiệm thời gian chỉnh sửa.

# # #

Xem các bài viết của David Fitzjarrell


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cài đặt phần mềm Oracle Database 12c trên Windows

  2. Làm thế nào tôi có thể nhận được số ngày giữa 2 ngày trong Oracle 11g?

  3. Làm thế nào để có được ngày hôm qua trong Oracle

  4. Tên cột bảng Oracle có khoảng trắng

  5. Lý do tại sao oracle phân biệt chữ hoa chữ thường?