【问题标题】:execute IMMEDIATE plsql立即执行 plsql
【发布时间】:2022-06-11 00:35:01
【问题描述】:

我遇到了以下错误:

ORA-00923:在预期的地方找不到 FROM 关键字

在尝试构建 plsql 脚本时:

   declare 
    yearmonth varchar2(20) := &yearmonth ; 
    begin 
    execute IMMEDIATE 'CREATE TABLE tbl_board_new_method AS  
    with a as (  
    select u.*,case when ooo.terminal_number is not null then "BOX" else "NOBOX" end ISBOX  from (
    select q.*,
    CASE WHEN   substr(i.min_trn_date, 0, 8) IS NOT NULL AND  substr(i.min_trn_date, 0, 8)  <  coalesce(   substr(i.install_date, 0, 8) , q.install_date )  THEN 
    coalesce(   substr(i.min_trn_date, 0, 8) , q.install_date,  substr(i.install_date, 0, 8))  ELSE 
    coalesce(q.install_date,
    substr(i.install_date, 0, 8),
    substr(i.min_trn_date, 0, 8))  END f_install_date, 
    nvl(q.disable_date, substr(i.disable_date, 0, 8)) f_disable_date,
    q.pos_model pos_model1,
    q.pos_brand pos_brand1,
    q.pos_brand_model pos_brand_model1 ,
    CASE
      WHEN UPPER(q.pos_model) IN
      (:COMBO,
      "DIALUP",
      "LAN",
    "BRANCH") THEN
    "POS"
    ELSE
    CASE
    WHEN UPPER(q.pos_model) IN
    ("PCPOS", "TYPICAL") THEN
    "PCPOS"
    ELSE
    CASE
    WHEN UPPER(q.pos_model) IN
    ("MPOS(BT/INTERNET)",
    "MPOS") THEN
    "MPOS"
    ELSE
    CASE
    WHEN UPPER(q.pos_model) =
    "GPRS" THEN
    "GPRS"
    ELSE
    CASE
    WHEN UPPER(q.pos_model) =
    "IPG" THEN
    "IPG"
    ELSE
    "POS"
    END
    END
    END
    END
    
    from trg.tbl_merchant_info q
    left join trg.mvw_terminal_indicators i  on (q.terminal_number = i.terminal_number)
    where coalesce(q.install_date,
    substr(i.install_date, 0, 8),
    substr(i.min_trn_date, 0, 8)) is not null
    and 
    CASE WHEN   substr(i.min_trn_date, 0, 8) IS NOT NULL AND  substr(i.min_trn_date, 0, 8) <    substr(i.install_date, 0, 8)  THEN 
    coalesce(   substr(i.min_trn_date, 0, 8) , q.install_date,  substr(i.install_date, 0, 8))  ELSE 
    coalesce(q.install_date,
    substr(i.install_date, 0, 8),
    substr(i.min_trn_date, 0, 8)) END   <=  '||yearmonth||'||30
    and (nvl(q.disable_date, substr(i.disable_date, 0, 8)) is null OR  nvl(q.disable_date, substr(i.disable_date, 0, 8)) >='||yearmonth||'||01
    ) 
    and (trim(q.pos_model) is null or
    not
    (upper(q.pos_model) like "%MPOS%"  ))
    --- union 
    UNION 
    select q.*,
    CASE WHEN   substr(i.min_trn_date, 0, 8) IS NOT NULL AND  substr(i.min_trn_date, 0, 8)  <    coalesce(   substr(i.install_date, 0, 8) , q.install_date )  THEN 
    coalesce(   substr(i.min_trn_date, 0, 8) , q.install_date,  substr(i.install_date, 0, 8))  ELSE 
    coalesce(q.install_date,
    substr(i.install_date, 0, 8),
    substr(i.min_trn_date, 0, 8))  END f_install_date,
    nvl(q.disable_date, substr(i.disable_date, 0, 8)) f_disable_date,
    q.pos_model pos_model1,
    q.pos_brand pos_brand1,
    q.pos_brand_model pos_brand_model1 ,
    CASE
    WHEN UPPER(q.pos_model) IN
    ("COMBO",
    "POS",
    "DIALUP",
    "LAN",
    "BRANCH") THEN
    "POS"
    ELSE
    CASE
    WHEN UPPER(q.pos_model) IN
    ("PCPOS", "TYPICAL") THEN
    "PCPOS"
    ELSE
    CASE
    WHEN UPPER(q.pos_model) IN
    ("MPOS(BT/INTERNET)",
    "MPOS") THEN
    "MPOS"
    ELSE
    CASE
    WHEN UPPER(q.pos_model) =
    "GPRS" THEN
    "GPRS"
    ELSE
    CASE
    WHEN UPPER(q.pos_model) =
    "IPG" THEN
    "IPG"
    ELSE
    "POS"
    END
    END
    END
    END
    END FINAL_POS_MODEL
    from   trg.tbl_merchant_info q  
    left join trg.mvw_terminal_indicators i
    on (q.terminal_number = i.terminal_number)
    WHERE q.terminal_number IN (SELECT terminalno FROM trg.fct_total_aggrigate_daily d  WHERE substr(trn_date,0,6) = substr('||yearmonth||',0,6) )  
    ) u left join (select * from  trg.mvw_terminal_indicators  ooo 
    where   ooo.box_install is not null and (box_uninstall is null or  substr(ooo.box_uninstall,0,8)>= '||yearmonth||'||01) )  ooo on (ooo.terminal_number = u.terminal_number )
    a.terminal_number = t111.terminalno (+) and a.terminal_number = tt211.terminalno (+) and 
    a.terminal_number = ttt311.terminalno (+) and a.terminal_number = tttt411.terminalno (+) and a.terminal_number = ttttt511.terminalno (+)
    )
    --, pre AS (
    select terminalid, 
    case when m.scale_install is not null then 1 else 0 end   scale_install  ,
    yearmonth
    from p  left join  trg.mvw_terminal_indicators m on (p.terminal_number = m.terminal_number)';
    end ;

【问题讨论】:

  • 这个查询太复杂了(至少对我来说)。与其执行它,不如将其存储到一个局部变量中并在屏幕上显示(使用 dbms_output.put_line)。然后复制/粘贴它并在指向错误的工具中运行它。我看到的是你引用了一些:COMBO 的东西——这肯定行不通,所以你可能想删除一个冒号。除此之外,我无法运行该代码,因为我没有您的表格。
  • 是的,我明白了,但是因为代码很多,我无法完成。我删除了标志:但这不是原因。你有什么意见? _小脚丫
  • 你认为投注中的部分和这个符号“”里面的字符是正确的吗?
  • 声明 yearmonth varchar2(20) := &yearmonth ;开始执行 IMMEDIATE 'CREATE TABLE tbl_board_new_method AS as (select u.*,case when ooo.terminal_number is not null then "BOX" else "NOBOX" end ISBOX from (select q.*
  • 从创建表的第 4 行获取错误

标签: oracle plsql


【解决方案1】:

问题的一部分是 sql 中的双引号字符串,它们被视为标识符。 这是一个小测试。

-- test data
CREATE TABLE a_table (ID Number(3), COL1 VarChar2(20), COL2 VarChar2(20));
INSERT INTO a_table VALUES(1, 'AAA', 'BBB');
INSERT INTO a_table VALUES(1, 'BBB', 'CCC');
INSERT INTO a_table VALUES(1, 'CCC', 'AAA');
--
--  Creating sql comands with double and single quated strings
SET SERVEROUTPUT ON
Declare
    sq      VarChar2(1) := '''';
    myID    Number(3) := 1;
    mySql   VarChar2(1000);
    mySql2  VarChar2(1000);
Begin
    mySql := 'Select COL1, COL2  From a_table Where COL1 IN("AAA") And ID = 1';
    DBMS_OUTPUT.PUT_LINE(mySql);
    --
    mySQL2 := 'Select COL1, COL2  From a_table Where COL1 IN(' || sq || 'AAA' || sq || ') And ID = 1';
    DBMS_OUTPUT.PUT_LINE(mySql2);
End;
/
--
--  double quated string in sql throws an error 
Select COL1, COL2  From a_table Where COL1 IN("AAA") And ID = 1
--      SQL Error: ORA-00904: "AAA": invalid identifier
--
-- this one works
Select COL1, COL2  From a_table Where COL1 IN('AAA') And ID = 1
--      COL1                 COL2               
--      -------------------- --------------------
--      AAA                  BBB 

您的查询对我来说太大了无法分析,但大多数问题可能是双引号。在测试中,一个名为 sq 的变量用于保存单引号('''' --> 其中四个表示为单引号),然后,在编写 sql 命令时,该变量用于放置单引号进入有 varchar 类型值的命令。否则 Oracle 会尝试查找标识符。问候...

补充: 除了双引号之外,代码还有其他一些问题。 我从您的问题中提取了它,并对其进行了结构化以使其更具可读性。 问题在下面的代码中进行了注释,有一些代码丢失,一些错误,还有一些我无法理解。 这是结构化版本,问题在 [26, 45, 107, 116, 124, 125] 行和主 SELECT [第 128 - 138 行] 你会知道我没有抓住的东西,也许会让它发挥作用......

CREATE TABLE 
    tbl_board_new_method AS 
        
    with a as 
        (  
            Select 
                u.*,
                CASE WHEN ooo.terminal_number Is Not Null THEN "BOX" ELSE "NOBOX" END as ISBOX  
            From 
                (
                    Select 
                        q.*,
                        CASE 
                            WHEN substr(i.min_trn_date, 0, 8) IS NOT NULL AND  substr(i.min_trn_date, 0, 8)  <  coalesce(substr(i.install_date, 0, 8) , q.install_date )  
                            THEN coalesce(substr(i.min_trn_date, 0, 8) , q.install_date,  substr(i.install_date, 0, 8))  
                        ELSE 
                            coalesce(q.install_date, substr(i.install_date, 0, 8), substr(i.min_trn_date, 0, 8))  
                        END as F_INSTALL_DATE, 
                        --
                        Nvl(q.disable_date, substr(i.disable_date, 0, 8)) as F_DISABLE_DATE,
                        q.pos_model as POS_MODEL1,
                        q.pos_brand as POS_BRAND1,
                        q.pos_brand_model as POS_BRAND_MODEL1,
                        --
                        CASE
                          WHEN UPPER(q.pos_model) IN(:COMBO, "DIALUP", "LAN", "BRANCH") THEN "POS"              -- here was :COMBO -> I put "COMBO" as it is in second (unioned) query
                        ELSE
                            CASE
                                WHEN UPPER(q.pos_model) IN("PCPOS", "TYPICAL") THEN "PCPOS"
                            ELSE
                                CASE
                                    WHEN UPPER(q.pos_model) IN("MPOS(BT/INTERNET)", "MPOS") THEN "MPOS"
                                ELSE
                                    CASE
                                        WHEN UPPER(q.pos_model) = "GPRS" THEN "GPRS"
                                    ELSE
                                        CASE
                                            WHEN UPPER(q.pos_model) = "IPG" THEN "IPG"
                                        ELSE
                                            "POS"
                                        END
                                    END
                                END
                            END
                        END  as FINAL_POS_MODEL         -- this row was missing
                    From 
                        trg.tbl_merchant_info q
                    Left Join 
                        trg.mvw_terminal_indicators i ON(q.terminal_number = i.terminal_number)
                    Where 
                        coalesce(q.install_date, substr(i.install_date, 0, 8), substr(i.min_trn_date, 0, 8)) is not null And 
                        CASE 
                            WHEN substr(i.min_trn_date, 0, 8) Is Not Null And substr(i.min_trn_date, 0, 8) < substr(i.install_date, 0, 8)  
                            THEN coalesce(substr(i.min_trn_date, 0, 8) , q.install_date,  substr(i.install_date, 0, 8))  
                        ELSE 
                            coalesce(q.install_date, substr(i.install_date, 0, 8), substr(i.min_trn_date, 0, 8)) END <= ' || yearmonth || ' || 30 And
                            (
                                nvl(q.disable_date, substr(i.disable_date, 0, 8)) is null OR  nvl(q.disable_date, substr(i.disable_date, 0, 8)) >= '|| yearmonth ||' || 01
                            ) And 
                            (trim(q.pos_model) is null 
                          OR 
                            Not (Upper(q.pos_model) like "%MPOS%"))
                    --
                    --
                  UNION 
                    --
                    --
                    Select 
                        q.*,
                        CASE 
                            WHEN substr(i.min_trn_date, 0, 8) Is Not Null And  substr(i.min_trn_date, 0, 8) < coalesce(substr(i.install_date, 0, 8) , q.install_date )  
                            THEN coalesce(substr(i.min_trn_date, 0, 8) , q.install_date,  substr(i.install_date, 0, 8))  
                        ELSE 
                            coalesce(q.install_date, substr(i.install_date, 0, 8), substr(i.min_trn_date, 0, 8))  
                        END as F_INSTALL_DATE, 
                        Nvl(q.disable_date, substr(i.disable_date, 0, 8)) as F_DISABLE_DATE,
                        q.pos_model as POS_MODEL1,
                        q.pos_brand as POS_BRAND1,
                        q.pos_brand_model as POS_BRAND_MODEL1 ,
                        CASE
                            WHEN UPPER(q.pos_model) IN("COMBO", "POS", "DIALUP", "LAN", "BRANCH") THEN "POS"
                        ELSE
                            CASE
                                WHEN UPPER(q.pos_model) IN("PCPOS", "TYPICAL") THEN "PCPOS"
                            ELSE
                                CASE
                                    WHEN UPPER(q.pos_model) IN("MPOS(BT/INTERNET)", "MPOS") THEN "MPOS"
                                ELSE
                                    CASE
                                        WHEN UPPER(q.pos_model) = "GPRS" THEN "GPRS"
                                    ELSE
                                        CASE
                                            WHEN UPPER(q.pos_model) = "IPG" THEN "IPG"
                                        ELSE
                                            "POS"
                                        END
                                    END
                                END
                            END
                        END as FINAL_POS_MODEL
                    From   
                        trg.tbl_merchant_info q  
                    Left Join 
                        trg.mvw_terminal_indicators i ON(q.terminal_number = i.terminal_number)
                    Where 
                        q.terminal_number IN(   SELECT terminalno 
                                                FROM trg.fct_total_aggrigate_daily -- d -> table alias d excluded as not needed nor used in subquery
                                                WHERE substr(trn_date, 0, 6) = substr(' || yearmonth || ', 0, 6)
                                            )  
                ) u 
            Left Join 
                (
                    select 
                        * 
                    from  
                        trg.mvw_terminal_indicators ooo         -- ooo here as table alias is the same as the whole subquery alias  --> it can stay (used in where) but confusing 
                    Where 
                        ooo.box_install Is Not Null And 
                        (
                            box_uninstall Is Null OR substr(ooo.box_uninstall,0,8) >= ' || yearmonth || ' || 01
                        ) 
                )  ooo ON(ooo.terminal_number = u.terminal_number) 
        -- there should probably be WHERE clause here but I don't know what are next 2 lines - using alias [a] before it was created !?? (closing bracket in third line below ends creation of CTE named a) 
            a.terminal_number = t111.terminalno (+) and a.terminal_number = tt211.terminalno (+) and 
            a.terminal_number = ttt311.terminalno (+) and a.terminal_number = tttt411.terminalno (+) and a.terminal_number = ttttt511.terminalno (+)
        )
-- after end of creation of CTE named [a] (line 126) --> below should be the main select but you are selecting FROM p (what is p) joined with trg.mvw_terminal_indicators (nothing selected from [a])
SELECT 
    terminalid, 
    CASE 
        WHEN m.scale_install Is Not Null THEN 1 
    ELSE 0 
    END as SCALE_INSTALL,
    yearmonth       
FROM 
    p  -- what is p   -->   you are not selecting anything from (CTE) named [a]
LEFT JOIN  
    trg.mvw_terminal_indicators m ON(p.terminal_number = m.terminal_number)

仍然存在双引号问题,但可以使用任何文本编辑器来解决。 声明变量以保存 sql 代码字符串,声明 sq 变量并将 '''' 作为它的值并将 ["] 替换为 [' || sq || ']。然后打印代码 (DBMS_OUTPUT) 复制它,检查它并运行它。可能需要进行更多更正,但您会收到错误消息,问题是什么以及问题出在哪里。

【讨论】:

    猜你喜欢
    • 2018-04-19
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多