2017-10-12 70 views
0

我需要一個創建一個sql腳本,它將從表中以下列方式構建一個動態sql請求: select ID || ','||姓名|| ','||來自TABLE_TEST的代碼 ;從表列中創建動態SQL選擇

表名作爲輸入參數接收。

我的SQL腳本如下;

spool exportTable.log 
SET HEAD OFF 
SET TRIMOUT ON 
SET TRIMSPOOL ON 
SET LINESIZE 32000 
SET PAGESIZE 0 
SET TERMOUT OFF 
SET ECHO OFF 
SET COLSEP , 
procedure CreerReq(sTable in Varchar) is 

dbms_output.put_line('dans CreerReq'); 
sqlreq VARCHAR2(2000); 
sChaine VARCHAR2(4000):='select'; 
TYPE t_tab IS TABLE OF VARCHAR2(4000); 
l_tab t_tab; 
l_tab_Id t_tab; 
l_ref_cursor SYS_REFCURSOR; 
dbms_output.put_line(sChaine); 

begin 
    sqlreq := 'select column_name from all_tab_cols WHERE table_name' || sTable; 
    dbms_output.put_line(sqlreq); 
    OPEN l_ref_cursor FOR sqlreq; 
    LOOP 
    FETCH l_ref_cursor BULK COLLECT INTO l_tab_Id,l_tab limit 1000; 
    EXIT WHEN l_tab.COUNT=0; 
    FOR i IN l_tab.first .. l_tab.last LOOP 
     sChaine:=l_tab(i) ' || ',''; 
    END LOOP; 
    CLOSE l_ref_cursor; 
    dbms_output.put_line(sChaine); 
End CreerReq; 

BEGIN 


dbms_output.put_line('&1'); 
    CreerReq(&1); 
END; 
/
spool off; 

但是這回我下面的錯誤:

ORA-00900: invalid SQL statement

任何幫助嗎?

回答

0
CREATE or replace FUNCTION build_select (
    p_owner  IN VARCHAR2 
    , p_table_name IN VARCHAR2 
) 
    RETURN VARCHAR2 
AS 
    l_ret VARCHAR2 (32767); 
BEGIN 
    FOR eachcol IN ( SELECT column_name 
          , LEAD (column_name) 
           OVER (
            PARTITION BY table_name ORDER BY column_id 
           ) 
           next_column 
         FROM all_tab_cols 
         WHERE owner = p_owner 
         AND table_name = p_table_name 
        ORDER BY column_id) 
    LOOP 
     l_ret := l_ret || eachcol.column_name || CASE WHEN eachcol.next_column IS NULL THEN NULL ELSE ',' END; 
    END LOOP; 

    IF l_ret IS NULL 
    THEN 
     raise_application_error (-20001, 'table ' || p_owner || '.' || p_table_name || ' not found'); 
    END IF; 

    l_ret := 'select ' || l_ret || ' from ' || p_owner || '.' || p_table_name; 

    RETURN l_ret; 
END build_select; 

因此,讓我們測試一下:

begin dbms_output.put_line(build_select('SYS', 'ALL_TAB_COLS')); end; 

結果:

select OWNER,TABLE_NAME,COLUMN_NAME,DATA_TYPE,DATA_TYPE_MOD,DATA_TYPE_OWNER,DATA_LENGTH,DATA_PRECISION,DATA_SCALE,NULLABLE,COLUMN_ID,DEFAULT_LENGTH,DATA_DEFAULT,NUM_DISTINCT,LOW_VALUE,HIGH_VALUE,DENSITY,NUM_NULLS,NUM_BUCKETS,LAST_ANALYZED,SAMPLE_SIZE,CHARACTER_SET_NAME,CHAR_COL_DECL_LENGTH,GLOBAL_STATS,USER_STATS,AVG_COL_LEN,CHAR_LENGTH,CHAR_USED,V80_FMT_IMAGE,DATA_UPGRADED,HIDDEN_COLUMN,VIRTUAL_COLUMN,SEGMENT_COLUMN_ID,INTERNAL_COLUMN_ID,HISTOGRAM,QUALIFIED_COL_NAME from SYS.ALL_TAB_COLS 

這裏是一個更簡單的build_select功能:

CREATE OR REPLACE FUNCTION build_select (
    p_owner  IN VARCHAR2 
    , p_table_name IN VARCHAR2 
) 
    RETURN VARCHAR2 
AS 
    l_ret VARCHAR2 (32767); 
BEGIN 
    SELECT  
      LISTAGG (column_name, ',') WITHIN GROUP (ORDER BY column_id) 
     INTO l_ret 
     FROM all_tab_cols 
    WHERE table_name = p_table_name 
     AND owner = p_owner; 

    IF l_ret IS NULL 
    THEN 
     raise_application_error (-20001, 'table ' || p_owner || '.' || p_table_name || ' not found'); 
    END IF; 

    l_ret := 'select ' || l_ret || ' from ' || p_owner || '.' || p_table_name; 

    RETURN l_ret; 
END build_select; 
-1

我一段時間沒有和oracle一起工作過。但在SQL Server上,這是如何完成的。來看看這代碼,它可能指向你到正確的方向:

/* This stored procedure builds dynamic SQL and executes 
using sp_executesql */ 
Create Procedure sp_EmployeeSelect 
    /* Input Parameters */ 
    @EmployeeName NVarchar(100), 
    @Department NVarchar(50), 
    @Designation NVarchar(50), 
    @StartDate DateTime, 
    @EndDate DateTime, 
    @Salary Decimal(10,2) 

AS 
    Set NoCount ON 
    /* Variable Declaration */ 
    Declare @SQLQuery AS NVarchar(4000) 
    Declare @ParamDefinition AS NVarchar(2000) 
    /* Build the Transact-SQL String with the input parameters */ 
    Set @SQLQuery = 'Select * From tblEmployees where (1=1) ' 
    /* check for the condition and build the WHERE clause accordingly */ 
    If @EmployeeName Is Not Null 
     Set @SQLQuery = @SQLQuery + ' And (EmployeeName = @EmployeeName)' 

    If @Department Is Not Null 
     Set @SQLQuery = @SQLQuery + ' And (Department = @Department)' 

    If @Designation Is Not Null 
     Set @SQLQuery = @SQLQuery + ' And (Designation = @Designation)' 

    If @Salary Is Not Null 
     Set @SQLQuery = @SQLQuery + ' And (Salary >= @Salary)' 

    If (@StartDate Is Not Null) AND (@EndDate Is Not Null) 
     Set @SQLQuery = @SQLQuery + ' And (JoiningDate 
     BETWEEN @StartDate AND @EndDate)' 
    /* Specify Parameter Format for all input parameters included 
    in the stmt */ 
    Set @ParamDefinition =  ' @EmployeeName NVarchar(100), 
       @Department NVarchar(50), 
       @Designation NVarchar(50), 
       @StartDate DateTime, 
       @EndDate DateTime, 
       @Salary Decimal(10,2)' 
    /* Execute the Transact-SQL String with all parameter value's 
     Using sp_executesql Command */ 
    Execute sp_Executesql  @SQLQuery, 
       @ParamDefinition, 
       @EmployeeName, 
       @Department, 
       @Designation, 
       @StartDate, 
       @EndDate, 
       @Salary 

    If @@ERROR <> 0 GoTo ErrorHandler 
    Set NoCount OFF 
    Return(0) 

ErrorHandler: 
    Return(@@ERROR) 
GO