如何在PLSQL中从数据库表中获取没有特定列名的数据?

huangapple go评论111阅读模式
英文:

How can i get data from db table without specific column name on PLSQL

问题

我有一个像这样的表;

ID Name Year pl_out (xml)
1 Ivan 1989 xx
2 Pep 1997 xx

当我尝试执行 "select * from my_table" 查询时,由于 pl_out 列很大,查询需要很长时间。

我不喜欢使用 "select ID, Name, Year from my_table" 的方式。也许有时我的表会有很多列。

那么,如何从数据库表中获取数据,而不需要指定列名?有没有办法?

就像 "select * from my_table where column_name!='pl_out'" 这样的方式。但是这不起作用([错误] 执行(9: 67):ORA-00904:"COLUMN_NAME":无效标识符)

谢谢!

我尝试从数据库表中获取不包含特定列名的数据。

英文:

I have a table like;

ID Name Year pl_out (xml)
1 Ivan 1989 xx
2 Pep 1997 xx

when i try "select * from my_table" query takes long time because of huge pl_out column.

i dont prefer "select ID,Name,Year from my_table" way. Maybe sometimes my table will have many colums.

so how can i get data from db table without specific column name ? is there any way ?

like "select * from my_table where column_name!='pl_out'"
it dosent work ([Error] Execution (9: 67): ORA-00904: "COLUMN_NAME": invalid identifier)

thanks !

I try get data from db table without specific column name

答案1

得分: 1

以下是翻译好的部分:

How can I get data from db table without specific column name?
如何从数据库表中获取没有特定列名的数据?

Make the column INVISIBLE then it will be excluded from SELECT * FROM table_name; but you can still select it if you explicitly name it.
将列设为 INVISIBLE,它将在 SELECT * FROM table_name; 中被排除,但如果您明确命名它,仍然可以选择它。

For example:
例如:

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;

Then:
然后:

SELECT * FROM table_name;

Outputs:
输出:

ID NAME YEAR
1 Alice 1900

And:
以及:

SELECT t.*, pl_out FROM table_name t;

Outputs:
输出:

ID NAME YEAR PL_OUT
1 Alice 1900 A big column you do not want.

fiddle

英文:

> How can I get data from db table without specific column name?

Make the column INVISIBLE then it will be excluded from SELECT * FROM table_name; but you can still select it if you explicitly name it.

For example:

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;

Then:

SELECT * FROM table_name;

Outputs:

ID NAME YEAR
1 Alice 1900

And:

SELECT t.*, pl_out FROM table_name t;

Outputs:

ID NAME YEAR PL_OUT
1 Alice 1900 A big column you do not want.

fiddle

答案2

得分: 0

你可以创建一个多态表函数,自 Oracle 18c 开始可用,它将跳过你指定的列。

注意:

这种方法应该谨慎使用,仅用于非常有限的情况,因为明确比隐式更好。要么指定星号(*)以表示你需要的一切,要么指定列,以指定期望的内容。

除了某些中间数据转换步骤可能会好一些,你可以在转换中定义那些额外的列(例如,在 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.
          默认为 TRUE,所以当需要时需要将其设为 FALSE*/
        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;
/*创建由包实现的 PTF*/
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

或者使用自 Oracle 19.7 起可用的 SQL 宏来实现相同的功能(似乎 DBMS_TF 参数自 21c 起可用,但我没有 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 |

状态:

dbms_output:

select "COL1","COL3" from p_tab

fiddle

英文:

You may create a Polymorphic Table Function available since 18c that will skip columns you specify.

Note:

This approach should be used carefully for very limited cases, because explicit is better than implicit. Either specify star (*) to designate that you want everything or specify columns you want to specify what is expected to be.

Everything except some may be okay as intermediate steps of data transformation where you define those extra columns right in the transformation (for example, union of two CTEs with adjustment of few columns like in unpivot). Otherwise you cannot know the future and cannot guarantee that new columns in the table are those you really want/expect: all except one means everything in the entire Universe except this particular entity.

PTF implementation is in below code:

>
> 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;/
>

Test the function:

>
> 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

Or the same with SQL Macro available since 19.7 (seems that DBMS_TF parameters are available since 21c, but I have no 19.7 to test this).

>
> 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

答案3

得分: 0

由于您有许多需要排除某些列的表格,也许您可以定义并将这些表格和排除项存储在一个表格中。下面是一个示例表格(我将其命名为SQL_EXEC),显示了三种不同类型的列排除。稍后将使用函数更新SQL_SELECT列。这是SQL_EXEC表格:

OWNER_NAME TABLE_NAME EXCL_TYPE EXCL_VAL SQL_SELECT
YOUR_OWNER TEST DATA_TYPE CLOB
YOUR_OWNER TEST DATA_LENGTH 4000
YOUR_OWNER TEST COLUMN_NAME PL_OUT

生成特定排除的SQL选择语句的函数可以如下所示:

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列。作为示例,我在TEST表上使用了它。

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

这将使用来自PL_OUT列的三种不同排除项派生的相同选择语句更新所有三行。

Select ID, A_NAME, A_YEAR From TEST

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

英文:

As you have many tables that need a kind of exclusion of certain column(s) maybe you could define and store those tables and exclusions in a table. Below is an example of such a table (I named it SQL_EXEC) showing three different types of excluding a column. The SQL_SELECT column will be updated later using a function. Here is the SQL_EXEC table:

OWNER_NAME TABLE_NAME EXCL_TYPE EXCL_VAL SQL_SELECT
YOUR_OWNER TEST DATA_TYPE CLOB
YOUR_OWNER TEST DATA_LENGTH 4000
YOUR_OWNER TEST COLUMN_NAME PL_OUT

The function that generates the SQL Select statement for certain exclusion could be like below:

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;

After having your data in SQL_EXEC table you can update the SQL_SELECT column using the function. As a sample I used it on the TEST table.

ID A_NAME A_YEAR PL_OUT
1 Ivan 1989 xx
2 Pep 1997 xx
UPDATE SQL_EXEC
    SET SQL_SELECT = Get_SQL(OWNER_NAME, TABLE_NAME, EXCL_TYPE, EXCL_VAL)

This will update all three rows with the same select statement derived from three different exclusions of PL_OUT column.

Select ID, A_NAME, A_YEAR From TEST

This could further be used either one by one or looped through in a dynamic way.

huangapple
  • 本文由 发表于 2023年6月13日 14:31:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76462194.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定