英文:
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. |
英文:
> 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. |
答案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 |
或者使用自 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
英文:
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 |
>
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
>
答案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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论