2012-01-03 91 views
5

如何在PL/SQL中打印记录变量的所有字段。 记录变量有很多字段,所以有比打印每个字段更好的方法吗? 也尝试过动态SQL,但没有帮助。在PL/SQL中打印记录字段

+0

您是否试图打印出数据库字段名称或值? – DOK 2012-01-03 19:04:18

+1

我正在尝试打印字段名称及其相应的值。 – Iban 2012-01-03 19:12:21

+0

我想你想要的是使用[光标](http://docs.oracle.com/cd/B14117_01/appdev.101/b10807/06_ora.htm#i36655)。我与DOK ...你想打印一个记录中的所有字段,而不打印每个字段?这个问题更精确的措辞可能会有所帮助。 – Dallas 2012-01-03 19:12:52

回答

0

如果它是在IDE中运行的PL/SQL块,那么您可以使用DBMS_OUTPUT来输出值。

http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_output.htm

例如:

SET SERVEROUTPUT ON 

DECLARE 
    -- Define the record 
    TYPE test_rectype IS RECORD (
     field1 NUMBER, 
     field2 VARCHAR2 
    ); 
    -- Define a variable for the record 
    test_rec TEST_RECTYPE; 
BEGIN 
    -- Populate the record 
    test_rec.field1 := 1; 
    test_rec.field2 := 'my value'; 
    -- Enable the DBMS_OUTPUT 
    DBMS_OUTPUT.enable(1000000); 
    -- Send the output to the buffer 
    DBMS_OUTPUT.put_line('Field1: '||test_rec.field1||', Field2: '||test_rec.field2); 
END; 

还有更多的DBMS_OUTPUT所以看一看从上面的链接的文档。

或者,您可以使用UTL_FILE将值写入文件。

http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/u_file.htm

希望它可以帮助...

+1

我正在使用的记录变量有超过50个字段。那么是否有比使用DBMS_OUTPUT.PUT_LINE所有50个字段更好的方法? – Iban 2012-01-03 19:23:20

6

上Ollies使用DBMS_OUTPUT的大厦,但动态地去通过游标

设立测试

/*create table temp (aa varchar2(50) , bb number , cc date) ; 

insert into temp (aa,bb,cc) 
    select chr(level+100) , level, sysdate+level 
    from dual 
    connect by level < 15 ; 
/
*/ 

显示测试的块(假设为11g)

set serveroutput on 
declare 
    l_cur SYS_REFCURSOR ; 

    PROCEDURE CursorOutput(
          p_refcursor  IN OUT SYS_REFCURSOR 
         ) 
    AS 
     l_desc   DBMS_SQL.DESC_TAB ; 
     l_cols   BINARY_INTEGER ; 
     l_cursor  BINARY_INTEGER ; 
     v_varchar2  VARCHAR2(4000) ; 
     v_number  NUMBER ; 
     v_date   DATE ; 
     l_data   varchar2(32767) ; 
     l_columnValue VARCHAR2(32767) ; 
     l_processedRows Number := 0; 
    BEGIN 

     /* Convert refcursor "parameter" to DBMS_SQL cursor... */ 
     l_cursor := DBMS_SQL.TO_CURSOR_NUMBER(p_refcursor); 
     /* Describe the cursor... */ 
     DBMS_SQL.DESCRIBE_COLUMNS(l_cursor, l_cols, l_desc); 

     /* Define columns to be fetched. We're only using V2, NUM, DATE for example... 
     for a complete list of the col_types this link is accessible. 
     http://download.oracle.com/docs/cd/B10501_01/server.920/a96540/sql_elements2a.htm#45504 
     http://forums.oracle.com/forums/thread.jspa?threadID=912475 
     if not a usable type, will throw new exception 
     */ 
     FOR i IN 1 .. l_cols LOOP 
      IF l_desc(i).col_type = 2 THEN 
       DBMS_SQL.DEFINE_COLUMN(l_cursor, i, v_number); 
      ELSIF l_desc(i).col_type = 12 THEN 
       DBMS_SQL.DEFINE_COLUMN(l_cursor, i, v_date); 
      ELSif l_desc(i).col_type = 01 or l_desc(i).col_type = 96 then 
       DBMS_SQL.DEFINE_COLUMN(l_cursor, i, v_varchar2, 4000); 
      else 
       --raise an exception if the user's query contains a datatype not (yet) supported by this procedure 
       RAISE_APPLICATION_ERROR(-20000, 'Invalid Data Type for conversion to delimited file. {' || l_desc(i).col_name || '}'); 
      END IF; 
      END LOOP; 


     /* -- print out the column names if desired 
      FOR i IN 1 .. l_cols LOOP 
        dbms_output.put_line('** ' || l_desc(i).col_name) ; 
      END LOOP; 
     */ 

     /* Fetch all data... */ 
     WHILE DBMS_SQL.FETCH_ROWS(l_cursor) > 0 LOOP 
      dbms_output.put_line('LINE: ' || l_processedRows || ''); 
      FOR i IN 1 .. l_cols LOOP 
       if l_desc(i).col_type = 12 THEN --we are in a date 
        DBMS_SQL.COLUMN_VALUE(l_cursor, i, v_date); 
        v_varchar2 := to_char(v_date , 'dd-MON-yyyy') ; 
       elsif l_desc(i).col_type = 2 THEN --we are in a number 
        DBMS_SQL.COLUMN_VALUE(l_cursor, i, v_number); 
        v_varchar2 := to_char(v_number) ; 
       else --treat it as a string (should be varchar2,char,etc) 
        DBMS_SQL.COLUMN_VALUE(l_cursor, i, v_varchar2); 
        IF v_varchar2 IS NOT NULL THEN 
         v_varchar2 := '"' || v_varchar2 || '"' ; 
         ELSE 
         v_varchar2 := ''; 
        END IF ; 
       end if ; 
       dbms_output.put_line(l_desc(i).col_name || '=>' || v_varchar2) ; 
      END LOOP; 
      l_processedRows := l_processedRows + 1 ; 
      END LOOP; 

      dbms_sql.close_cursor(l_cursor); 
      dbms_output.put_line('I found and processed ' || l_processedRows || ' rows .'); 

    END; 

begin 
     open l_cur for select * from temp; 

     CursorOutput(p_refcursor => l_cur) ; 

end ; 
/

会给你这样的结果

LINE: 0 
AA=>"e" 
BB=>1 
CC=>04-JAN-2012 
LINE: 1 
AA=>"f" 
BB=>2 
CC=>05-JAN-2012 
LINE: 2 
AA=>"g" 
BB=>3 
CC=>06-JAN-2012 
LINE: 3 
AA=>"h" 
BB=>4 
CC=>07-JAN-2012 
LINE: 4 
AA=>"i" 
BB=>5 
CC=>08-JAN-2012 
LINE: 5 
AA=>"j" 
BB=>6 
CC=>09-JAN-2012 
LINE: 6 
AA=>"k" 
BB=>7 
CC=>10-JAN-2012 
LINE: 7 
AA=>"l" 
BB=>8 
CC=>11-JAN-2012 
LINE: 8 
AA=>"m" 
BB=>9 
CC=>12-JAN-2012 
LINE: 9 
AA=>"n" 
BB=>10 
CC=>13-JAN-2012 
LINE: 10 
AA=>"o" 
BB=>11 
CC=>14-JAN-2012 
LINE: 11 
AA=>"p" 
BB=>12 
CC=>15-JAN-2012 
LINE: 12 
AA=>"q" 
BB=>13 
CC=>16-JAN-2012 
LINE: 13 
AA=>"r" 
BB=>14 
CC=>17-JAN-2012 
I found and processed 14 rows . 

我做了类似这样的动态构建利用这两个环节为源CSV文件的东西 http://www.oracle-developer.net/display.php?id=505 http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:88212348059

根据但是,您可能只想在SQL Developer(或Toad)中运行它并导出r esults!

+0

这真的有帮助!但是,我得到的唯一输入是一个Record变量。我无法查询任何表格来形成游标。但是我知道这个记录所基于的表,因为它是使用ROWTYPE声明的。所以我只有一个记录(行)有很多字段可以打印。 – Iban 2012-01-03 19:39:07

+0

@伊班,错过了那部分,让我研究一下,看看这是否可能,如果是的话 - 怎么样 - 对不起! – Harrison 2012-01-04 14:18:38

+0

提前致谢!我也尝试过使用动态SQL。我可以通过查询dba_tab_columns来获取字段名称,因为我知道记录所基于的表。但是,该记录超出了动态SQL块中的范围,因此它是错误的。 – Iban 2012-01-04 16:09:29