oracle 我如何从数据库表中获取数据,而不需要PLSQL上的特定列名[重复]

ma8fv8wu  于 2023-06-22  发布在  Oracle
关注(0)|答案(3)|浏览(120)

此问题已在此处有答案

Can you SELECT everything, but 1 or 2 fields, without writer's cramp?(12个回答)
7天前关闭
我有一张table像;
| ID|姓名|年份|pl_out(xml)|
| - -----|- -----|- -----|- -----|
| 1|伊万|一九八九年|xx|
| 2|佩普|一九九七年|xx|
当我尝试“select * from my_table”查询需要很长时间,因为巨大的pl_out列。
我不喜欢“从我的表中选择ID,姓名,年份”的方式。也许有时我的表会有很多列。
那么我如何从没有特定列名数据库表中获取数据呢?有什么办法吗?
比如“select * from my_table where column_name!='pl_out'“
it dosent work([Error] Execution(9:67):ORA-00904:“COLUMN_NAME”:无效标识符)
谢谢!
我试着从没有特定列名的db表中获取数据

bnlyeluc

bnlyeluc1#

如何从没有特定列名的数据库表中获取数据?
将列设为INVISIBLE,则它将从SELECT * FROM table_name;中排除,但如果显式命名它,您仍然可以选择它。
例如:

CREATE TABLE table_name (ID, Name, Year, pl_out) AS
SELECT 1, 'Alice', 1900, 'A big column you do not want.' FROM DUAL;

ALTER TABLE table_name MODIFY pl_out INVISIBLE;

然后:

SELECT * FROM table_name;

输出:
| ID|名称|年份|
| - -----|- -----|- -----|
| 1|爱丽丝|一九○ ○年|
并且:

SELECT t.*, pl_out FROM table_name t;

输出:
| ID|名称|年份|PL_OUT|
| - -----|- -----|- -----|- -----|
| 1|爱丽丝|一九○ ○年|一个你不想要的大专栏。|
fiddle

mm5n2pyu

mm5n2pyu2#

您可以创建自18c起可用的多态表函数,该函数将跳过您指定的列。

注意:

在非常有限的情况下应谨慎使用这种方法,因为显式比隐式更好。指定star(*)来指定您想要的所有内容,或者指定您想要指定的列。
除了一些列之外,其他的都可以作为数据转换的中间步骤,在这些步骤中,您可以在转换中定义这些额外的列(例如,像unpivot中那样,通过调整几个列来合并两个CTE)。否则,您无法知道未来,也无法保证表中的新列是您真正想要/期望的列:除了一个之外的所有意味着整个宇宙中的一切,除了这个特定的实体。
PTF实现在以下代码中:

create package pkg_projection_ptf as
  function describe(
    p_table in out dbms_tf.table_t,
    p_exclude_cols dbms_tf.columns_t
  ) return dbms_tf.describe_t;
end pkg_projection_ptf;/
create package body pkg_projection_ptf as
  function describe(
    /*Table identifier*/
    p_table in out dbms_tf.table_t,
    /*List of column identifiers*/
    p_exclude_cols dbms_tf.columns_t
  ) return dbms_tf.describe_t
  as
  begin
    for i in 1..p_table.column.count loop
      for j in 1..p_exclude_cols.count loop
        /*pass_through = visible for subsequent processing.
          Is TRUE by default, so we need to make it FALSE when required*/
        p_table.column(i).pass_through := p_exclude_cols(j) != p_table.column(i).description.name;
        exit when p_table.column(i).pass_through = false;
      end loop;
    end loop;

    return null;
  end;
end pkg_projection_ptf;/
/*Create PTF that is implemented by the package*/
create function f_projection_exclude(
    p_table in out table,
    p_exclude_cols columns
  )
return table
pipelined row polymorphic
using pkg_projection_ptf;/

测试功能:

create table sample_table (col1, col2, col3) as
  select 1, 2, 3 from dual
select *
from f_projection_exclude(
  /*Table name and column names are identifiers here, not text literals*/
  p_table => sample_table,
  p_exclude_cols => columns(col2, col3)
)

| COL1 |
| -----|
| 1    |
select *
from f_projection_exclude(
  p_table => sample_table,
  p_exclude_cols => columns(col1)
)

| COL2 | COL3 |
| -----|------|
| 2    | 3    |

fiddle
或者从19.7开始使用SQL宏(似乎从21c开始使用DBMS_TF参数,但我没有19.7来测试)。

with function f(
  p_tab dbms_tf.table_t,
  p_cols dbms_tf.columns_t
)
return varchar2
sql_macro(table)
as
  l_keep_col boolean;
  l_cols varchar2(1000);
  l_stmt varchar2(1000);
begin
  for i in 1..p_tab.column.count loop
    l_keep_col := true;
    for j in 1..p_cols.count loop
      if p_tab.column(i).description.name = p_cols(j) then
        l_keep_col := false;
        exit;
      end if;
    end loop;

    if l_keep_col then
      l_cols := l_cols || ',' || p_tab.column(i).description.name;
    end if;
  end loop;

  l_stmt := 'select ' || trim( both ',' from l_cols) || ' from p_tab';
  dbms_output.put_line(l_stmt);
  return l_stmt;
end;

select *
from f(sample_table, columns(col2))

| COL1 | COL3 |
| ----:|----:|
| 1 | 3 |

status

dbms_output:
select "COL1","COL3" from p_tab

fiddle

unhi4e5o

unhi4e5o3#

由于您有许多表需要排除某些列,因此您可以定义并存储这些表和表中的排除项。下面是这样一个表的示例(我将其命名为SQL_EXEC),显示了三种不同类型的列排除。SQL_SELECT列稍后将使用函数进行更新。下面是SQL_EXEC表:
| 所有者名称|表名|EXCL_类型|EXCL_瓦尔|SQL_SELECT|
| - -----|- -----|- -----|- -----|- -----|
| 您的_所有者|测试|数据类型|CLOB||
| 您的_所有者|测试|数据长度|四千||
| 您的_所有者|测试|列名称|PL_OUT||
为特定排除生成SQL Select语句的函数可能如下所示:

Create or Replace 
FUNCTION Get_SQL(p_owner VarChar2, p_table VarChar2, p_exclude_type VarChar2, p_exclude_value VarChar2) RETURN VarChar2 AS 
BEGIN
    Declare
        mRet         VarChar2(1000) := '';
        mExclusion   VarChar2(64);
        mSQL         VarChar2(1000);
        mCursor      SYS_REFCURSOR;
        mColumn      VarChar2(32);
        sq           VarChar2(1) := '''';
    Begin
        mExclusion := p_exclude_type || ' != ' || sq || p_exclude_value || sq;
        mSQL := 'Select COLUMN_NAME From all_tab_columns Where OWNER = ' || sq || p_owner || sq || ' And TABLE_NAME = ' || sq || p_table || sq || ' And ' || mExclusion;
        Open mCursor For mSQL;
        Loop
            Fetch mCursor Into mColumn;
            Exit When mCursor%NOTFOUND;
            mRet := mRet || mColumn || ', ';
        End Loop;
        If Length(mRet) > 0 Then
            mRet := 'Select ' || SubStr(mRet, 1, Length(mRet) - 2)  || ' From ' || p_table;
        End If;
        RETURN mRet;
    End;
END Get_SQL;

在SQL_EXEC表中有了数据之后,可以使用函数更新SQL_SELECT列。作为一个样本,我用它在测试表。
| ID| A_NAME| A_年|PL_OUT|
| - -----|- -----|- -----|- -----|
| 1|伊万|一九八九年|xx|
| 2|佩普|一九九七年|xx|

UPDATE SQL_EXEC
    SET SQL_SELECT = Get_SQL(OWNER_NAME, TABLE_NAME, EXCL_TYPE, EXCL_VAL)

这将使用从PL_OUT列的三个不同排除项派生的相同select语句更新所有三行。

Select ID, A_NAME, A_YEAR From TEST

这可以进一步逐个使用或以动态方式循环使用。

相关问题