簡體   English   中英

從表列創建動態SQL選擇

[英]Creating dynamic SQL select from table columns

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

表名稱作為輸入參數被接收。

我的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:無效的SQL語句

有什么幫助嗎?

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;

我已經有一段時間沒有與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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM