Oracle 除了1或2个字段外,您可以选择所有字段,而不受书写者的限制吗?

Oracle 除了1或2个字段外,您可以选择所有字段,而不受书写者的限制吗?,oracle,plsql,Oracle,Plsql,在PLSQL中,是否可以选择表中除1或2之外的所有字段,而不必指定所需的字段 例如,employee表包含以下字段: 身份证件 名字 姓氏 业余爱好 是否仍然可以编写类似的查询 select * from employee 当你离开这个领域的时候,你的业余爱好就不用写这样的东西了 select id, firstname, lastname from employee 否-。如果您想避免编写者的抽筋,可以使用SQL Developer并让它为您生成列列表: select column_nam

在PLSQL中,是否可以选择表中除1或2之外的所有字段,而不必指定所需的字段

例如,employee表包含以下字段:

身份证件 名字 姓氏 业余爱好 是否仍然可以编写类似的查询

select * from employee
当你离开这个领域的时候,你的业余爱好就不用写这样的东西了

select id, firstname, lastname from employee

否-。

如果您想避免编写者的抽筋,可以使用SQL Developer并让它为您生成列列表:

select column_name||','
from all_tab_columns
where table_name = 'YourTableName'
然后去掉你不想要的一两列

你也可以使用

SELECT listagg(column_name, ',') within group (order by column_name) columns
FROM all_tab_columns
WHERE table_name = 'TABLE_NAME'
GROUP BY table_name;
query_生成器是一个PL/SQL函数,它为表1参数返回一个select字符串,但不包括第2参数中的某些列

stringlist和putil.join来自

stringlist是一个简单的字符串列表:创建类型stringlist作为varchar232767的表;而putil.join只是一个普通的连接函数

create or replace function quote_list(p_list in stringlist)
return stringlist as
  v_list stringlist := stringlist();
begin
  v_list.extend(p_list.last);
  for i in p_list.first .. p_list.last loop
    v_list(i) := '''' || p_list(i) || '''';
  end loop;

  return v_list;
end;
/
show errors

create or replace function query_generator(
  p_table in varchar2,
  p_exclude in stringlist
) return varchar2 as
  v_table constant varchar2(31) := upper(p_table);
  v_exclude constant varchar2(32676) :=
    upper(putil.join(quote_list(p_exclude), ','));
  v_stmt_str constant varchar2(32676) :=
    'select column_name from all_tab_columns where table_name = ''' ||
    v_table || ''' and column_name not in (' || v_exclude ||
    ') order by column_id';
  type stmt_cur_t is ref cursor;
  v_stmt_cur stmt_cur_t;
  v_column_name varchar2(31);
  v_query varchar2(32676) := 'select ';
begin
  open v_stmt_cur for v_stmt_str;

  loop
    fetch v_stmt_cur into v_column_name;
    exit when v_stmt_cur%notfound;
    v_query := v_query || lower(v_column_name) || ', ';
  end loop;

  close v_stmt_cur;

  select rtrim(v_query, ', ') into v_query from dual;

  v_query := v_query || ' from ' || p_table || ';';

  return v_query;
end;
/
show errors
用法示例:

exec dbms_output.put_line(query_generator('all_tables', stringlist('segment_created', 'result_cache')))
要创建视图,请执行以下操作:-

创建视图名称为 从员工中选择id、名字、姓氏 我在哪里


注意:-这类似于数据库中的虚拟表,但它可以影响实际表中的值。

下面是另一个选项,用于获取允许您指定分隔符的字段列表:

select listagg(column_name, ', ') WITHIN GROUP (ORDER BY rownum)
from all_tab_columns
where table_name='table'

以下是解决方案。。。我需要除密码以外的所有列

选择列_name | |','
从“用户”选项卡中的“用户”列,其中的“用户”和“密码”列是一个旧线程,但是,是的。。。在Oracle中有一种方法可以做到这一点:

with

employee(id, firstname, lastname, hobbies) as
(
  select 1, 'a', 'b', '1' from dual union 
  select 2, 'a', 'b', '2' from dual union 
  select 3, 'a', 'b', '3' from dual union 
  select 4, 'c', 'd', '3' from dual union 
  select 5, 'e', 'f', '2' from dual  
)

select * 
from employee 
pivot
( 
  max(1) -- fake  
  for (hobbies) -- put the undesired columns here
  IN () -- no values here...
) 
where 1=1 -- and your filters here...
order by id
为了了解PIVOT是如何工作的,以及它解决问题的原因,让我们为我们的employee示例表举一个更好的例子:

select * 
from employee 
pivot
(
  max(id) foo,
  max(1)  bar
  for (hobbies) 
  IN ('2' as two, '3' as three)
)
结果如下:

FIRSTNAME | LASTNAME | TWO_FOO | TWO_BAR | THREE_FOO | THREE_BAR c d null null 4 1 e f 5 1 null null a b 2 1 3 1 因此,列嗜好永远不会被选中,就像在PIVOT子句中指定的列id一样。所有其他列都将分组并选中

好的,回到第一个查询,它工作有两个原因: 1-在分组过程中不会丢失任何行,因为id列是唯一的,并且没有为聚合指定任何列; 2-由于pivot生成N*M个新列,其中N=IN子句的值数,M=指定的聚合数,因此没有筛选器,并且单个无害聚合将生成0*1=0个新列,并将删除pivot子句中指定的列,这只是一个例子

对评论1的答复

这个问题的第一行是:。。。无需指定所需的字段。在所有其他答案中,建议的查询在SELECT子句中指定了所需的字段,但在我的语句中除外

另外,在问题标题中说。。。没有作家的抽筋。那么,识别作家抽筋的正确方法是什么?我最大的努力是预见一个好的SQL标准来解决这个问题,并与我的答案进行比较。事实上,我认为这个标准可能类似于SELECT*而不是[col1],[col2]

现在,我可以在两个查询中看到:

不需要的列的列表; 附加条款; 三个字符的从句-FOR和NOT;
这意味着您需要在我的方法中编写更多内容,因为您需要一个伪聚合和PIVOT子句。。。但它真的很少字符更多

您是否在Oracle 12c上运行

WITH O AS
(
SELECT 'SELECT ' || rtrim('NULL AS "Dummy",' || LISTAGG('"'||column_name || '"', ',' ) within group (ORDER BY COLUMN_NAME),',')|| ' FROM "'||TABLE_NAME||'"' AS SQL, TABLE_NAME  FROM USER_TAB_COLUMNS  GROUP BY (TABLE_NAME)
)
SELECT DBMS_XMLGEN.GETXMLTYPE ((SELECT REPLACE(SQL,',COLUMNNAME','') FROM O WHERE TABLE_NAME = 'TABLENAME')) FROM DUAL

如果是这样,考虑这是否符合你的需要:

alter table mytable modify column undesired_col_name INVISIBLE;

在这种情况下,列不需要的列名称将完全可用,但它将从任何SELECT*语句和类似语句中排除,例如,%ROWTYPE,就好像它不存在一样。

OP所查找的内容类似于:

SELECT * MINUS hobbies from...
要避免大量键入并纠正所有列名,最好的方法是打开表说明,剪切并粘贴所有列名,删除不需要的列名,用逗号分隔其余列名,并将它们放在一行或两行上


它简单、快速、准确,并且不会让下一个需要处理代码的人感到困惑

Oracle 18c多态表函数可以从表中选择所有内容并排除列列表:

select * from everything_but(employee, columns(hobbies));

ID   FIRSTNAME   LASTNAME
--   ---------   --------
1    John        Smith
创建该功能需要以下软件包,该软件包来自Tim Hall的网站。请注意,该包不包含任何特定于该表的内容-此解决方案适用于任何Oracle表

CREATE OR REPLACE PACKAGE poly_pkg AS

  FUNCTION everything_but(tab IN TABLE,
                          col IN COLUMNS)
  RETURN TABLE PIPELINED
  ROW POLYMORPHIC USING poly_pkg;

  FUNCTION describe (tab IN OUT DBMS_TF.table_t,
                     col IN     dbms_tf.columns_t)
    RETURN DBMS_TF.describe_t;

END poly_pkg;
/


CREATE OR REPLACE PACKAGE BODY poly_pkg AS

  FUNCTION describe (tab IN OUT DBMS_TF.table_t,
                     col IN     dbms_tf.columns_t)
    RETURN DBMS_TF.describe_t
  AS
  BEGIN
    -- Loop through all the table columns.
    FOR i IN 1 .. tab.column.count() LOOP
      -- Loop through all the columns listed in the second parameter.
      FOR j IN 1 .. col.count() LOOP
        -- Set pass_through to true for any columns not in the exclude list.
        tab.column(i).pass_through := (tab.column(i).description.name != col(j));
        -- Exit inner loop if you find a column that shouldn't be included.
        EXIT WHEN NOT tab.column(i).pass_through;
      END LOOP;
    END LOOP;

    RETURN NULL;
  END;

END poly_pkg;
/
我还创建了这个简单的包装器函数来给它起一个更好的名字。并创建了一个简单的示例表

CREATE OR REPLACE FUNCTION everything_but(tab IN TABLE, col in COLUMNS)
  RETURN TABLE PIPELINED
  ROW POLYMORPHIC USING poly_pkg;
/

create table employee as
select 1 id, 'John' firstname, 'Smith' lastname, 'fishing' hobbies from dual;

这就是为什么SAS几十年来一直在其隐式SQL和数据步骤中提供DROP子句的原因

从myDB.mytabledrop=t中选择t.*

创建表/*或查看/mytabledrop= 选择t。来自myDB.myt表

无论有多少列,也不管myDB指向什么RDMBs,即ORACLE、Teradata、SAS、DB2、Netezza等。在将显式数据库SQL提交给RDMBs之前,SAS收集所有列名并删除指定的列名,以编程方式仅创建包含所需列的SELECT语句。

请不要在问题中添加签名。如果您经常只需要某些字段,则可以仅在这些列上创建视图。很高兴知道,但我希望在阅读结果插入时避免眼睛疲劳和书写者抽筋:。说真的,这很有用。我一直都在这么做。。。非常有用。Michael是对的,但您可以这样改进:从所有选项卡中选择wm_concatcolumn_name,其中table_name='your_table'我很懒,这样可以节省大量输入!有些人认为最好是避免选择*,并且总是指定所需的列。“我想避免选择*是最佳实践的一部分,但我不确定这是一个广泛的观点……”雅希亚:是的,选择*没有错,只要您能保证没有人会修改或重新创建表结构。永远/讽刺:在12c中,通过使列不可见,可以从SELECT*中排除列。请参见下面我的答案。当我使用动态生成的表进行联接时,除了用于联接的外键之外,我不知道从中联接的列名,我该如何做?如果您想完全自动化此过程,可以使用Oracle data cartridge执行字符串。查看本页的示例:这是一个非常强大的方法,但也非常复杂,并且存在一些问题。在文章底部添加了我对作家痉挛的观点,因为它的注释文本有点长……我无法想象在很多情况下,我真的想要做这个透视而不是写一个列列表的性能开销。但这是一个迷人的SQL解决方案!只是因为它激发了我的想象力——我更喜欢一个既可以删除不需要的列又可以重命名列的标准:选择*删除COL1,COL2将COL5重命名为NEW_COL FROM。。。编辑使成为主题:这个解决方案可以用来重命名列以及删除吗?谢谢,这是一个很酷的技巧。但是,如果您想在where子句中使用一个排除的列,它就不能按字面上所描述的那样工作。解决方案是使用包装选择,如:select*from select*from。。。哪里pivot…这是错误报告的黄金选择!我必须从许多表中导出数据,同时过滤掉所有错误数据并将其导出到不同的表/视图。这种方法可以很容易地创建一个errors列,我在其中向有某种错误的行发送信号,然后我就可以按照select*from select*from mytable(其中error=0)创建常规的视图correct_数据。。。要获取正确的数据,以及相应的创建视图,请将不正确的_数据作为select*from。。。错误0。。。我想你的意思是,我不会混淆-这在12C中不起作用,我得到ORA-00923:FROM关键字not found where expectedUday-我说它不起作用。只需从表描述中剪切并粘贴列名。此主题很旧,但现在它应该是可接受的答案。
CREATE OR REPLACE FUNCTION everything_but(tab IN TABLE, col in COLUMNS)
  RETURN TABLE PIPELINED
  ROW POLYMORPHIC USING poly_pkg;
/

create table employee as
select 1 id, 'John' firstname, 'Smith' lastname, 'fishing' hobbies from dual;