Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle 错误ORA-00998:必须使用列别名命名此表达式_Oracle_Plsql - Fatal编程技术网

Oracle 错误ORA-00998:必须使用列别名命名此表达式

Oracle 错误ORA-00998:必须使用列别名命名此表达式,oracle,plsql,Oracle,Plsql,我试图从所有列创建表,但它抛出了一个错误。 与错误ORA-00998类似:必须使用列别名命名此表达式。 我试着想办法,但没有成功 Declare CURSOR c1 IS SELECT COLUMN_NAME FROM (select 'standard_hash(MY_NAME) AS MY_NAME' COLUMN_NAME from DUAL UNION SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE TABLE_NAME='TABLE

我试图从所有列创建表,但它抛出了一个错误。 与错误ORA-00998类似:必须使用列别名命名此表达式。 我试着想办法,但没有成功

Declare

CURSOR c1 IS  

SELECT COLUMN_NAME FROM (select 'standard_hash(MY_NAME) AS MY_NAME' COLUMN_NAME from DUAL
UNION 
SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE TABLE_NAME='TABLE1' AND COLUMN_NAME<>'MY_NAME');

cols  c1%ROWTYPE;
sqlstmt  VARCHAR2(4000);

BEGIN
   OPEN c1;
     LOOP
         FETCH c1 into cols;
         EXIT WHEN c1%NOTFOUND;
         sqlstmt := sqlstmt ||cols.column_name||',';
      END LOOP;
   CLOSE c1;
   sqlstmt := 'CREATE TABLE TABLE2  AS SELECT '||substr(sqlstmt, 1, length(sqlstmt)-1)||' FROM TABLE1';
   DBMS_OUTPUT.PUT_LINE(sqlstmt);
   EXECUTE IMMEDIATE sqlstmt;
   EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('error '||sqlerrm);
END;
/

您只需为表达式指定名称,如下所示:

sqlstmt := 'CREATE TABLE TABLE2  AS SELECT '
           ||substr(sqlstmt, 1, length(sqlstmt)-1)
           ||' as column_name FROM TABLE1'; -- column_name will bre name of the column of new table

因为它将成为新创建表的列的名称。

我认为这可以简化一些

您不需要声明显式游标和记录类型并将每一行提取到其中,因为这已经作为构造内置到语言中:

declare
    sqlStmt long := 'create table table2 as select ';
begin
    for r in (
        select 'standard_hash(my_name) as my_name' column_name
        from   dual
        union
        select column_name
        from   all_tab_columns
        where  table_name = 'TABLE1'
        and    column_name <> 'MY_NAME'
    )
    loop
        sqlStmt := sqlStmt || r.column_name || ', ';
    end loop;

    sqlStmt := sqlStmt || rtrim(sqlStmt,', ') || ' from table1';

    dbms_output.put_line(sqlStmt);
    execute immediate sqlStmt;
end;
/

谢谢,所以标准的_hashMY_NAME作为最后一列出现,所以列_NAME按预期工作,我怀疑从dual中选择的列是否会被放在select语句的末尾,这对于所有表的创建都是一样的?您能告诉我,如果从dual中选择“standard\u hashYOUR\u NAME”列\u NAME从dual UNION中选择column\u NAME从select“standard\u hashMY\u NAME”列\u NAME从dual中选择column\u NAME。。。在这个场景中,我们还需要像你提到的那样使用吗?你在评论中发布的查询中没有多个列。注释中的查询将以列名称作为别名。这是否回答了您的问题@astentx不,但有点不同,我看是一样的。在另一个问题中,他们试图创建一个以一列作为表达式的表,而不为该列指定任何表达式名称。解决方案是将其命名为.A,这将大大简化您的代码。@WilliamRobertson您能举一些例子作为回答吗哇,非常感谢,这就是我要找的,由于列顺序的变化,我计划从所有列中获取列名,我可以知道有关create语句的一些解释吗?我可以使用CLOB吗,因为查询长度可能超过4000个字符,所以CLOB可以正常工作。但是,现在您已经提到了,listagg最多只能返回4000个字符,因此如果列列表+分隔符超过此值,则需要循环方法。但如果使用循环方法,则会更改列的默认顺序,可以将循环方法调整为按默认列IDOrder by column_id排序。
declare
    selectList  long;
    sqlStmt     long;
begin
    select listagg(
               case column_name
                   when 'MY_NAME' then 'standard_hash(my_name) as my_name'
                   else lower(column_name)
               end, ', '
           ) within group (order by column_id) as select_list
    into   selectList
    from   user_tab_columns c
    where  c.table_name = 'TABLE1';
    
    sqlStmt :=
        'create table table2 pctfree 0 nologging parallel as '||chr(10)||
        'select '||selectList||chr(10)||
        'from table1';

    dbms_output.put_line(sqlStmt||';');
    execute immediate sqlstmt;
end;