如何用oracle动态查询一张表里面的某些列?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何用oracle动态查询一张表里面的某些列?相关的知识,希望对你有一定的参考价值。

比如说:Table A有A1,A2,A3,A4,A5这5列,我能不能根据参数对比来select这张表里面的数据,就是select x1,x2...from A的时候想x1,x2...作为参数和A1,A2,A3,A4,A5比对,比对成功就选择这一列,不成功就不选择这一列
如何实现

在PLSQL中使用EXECUTE IMMEDIATE语句处理动态SQL语句。

语法如下:
EXECUTE IMMEDIATE dynamic_string
[INTO define_variable[, define_variable]... | record]
[USING [IN | OUT | IN OUT] bind_argument
[, [IN | OUT | IN OUT] bind_argument]...]
[RETURNING | RETURN INTO bind_argument[, bind_argument]...];
dynamic_string是代表一条SQL语句或一个PL/SQL块的字符串表达式,
define_variable是用于存放被选出的字段值的变量,
record是用户定义或%ROWTYPE类型的记录,用来存放被选出的行记录。
输入bind_argument参数是一个表达式,它的值将被传入(IN模式)或传出(OUT模式)或先传入再传出(IN OUT模式)到动态SQL语句或是PL/SQL块中。一个输出bind_argument参数就是一个能保存动态SQL返回值的变量。
除了多行查询外,动态字符串可以包含任何SQL语句(不含终结符)或PL/SQL块(含终结符)。
字符串中可以包括用于参数绑定的占位符。
但是,不可以使用绑定参数为动态SQL传递模式对象。
在用于单行查询时,INTO子句要指明用于存放检索值的变量或记录。
对于查询检索出来的每一个值,INTO子句中都必须有一个与之对应的、类型兼容的变量或字段。
在用于DML操作时,RETURNING INTO子句要指明用于存放返回值的变量或记录。
对于DML语句返回的每一个值,INTO子句中都必须有一个与之对应的、类型兼容的变量或字段。
我们可以把所有的绑定参数放到USING子句中。默认的参数模式是IN。
对于含有RETURNING子句的DML语句来说,我们可以把OUT参数放到RETURNING INTO之后,并且不用指定它们的参数模式,因为默认就是OUT。
如果我们既使用了USING又使用RETURNING INTO,那么,USING子句中就只能包含IN模式的参数了。
运行时,动态字符串中的绑定参数会替换相对应的占位符。所以,每个占位符必须与USING子句和/或RETURNING INTO子句中的一个绑定参数对应。我们可以使用数字、字符和字符串作为绑定参数,但不能使用布尔类型(TRUE,FALSE和NULL)。要把空值传递给动态字符串,我们就必须使用工作区。
动态SQL支持所有的SQL类型。所以,定义变量和绑定变量都可以是集合、LOB,对象类型实例和引用。
作为一项规则,动态SQL是不支持PL/SQL特有的类型的。这样,它就不能使用布尔型或索引表。
我们可以重复为绑定变量指定新值执行动态SQL语句。但是,每次都会消耗很多资源,因为EXECUTE IMMEDIATE在每次执行之前都需要对动态字符串进行预处理。追问

能不能给个简短的例子呢?刚接触不是很了解

追答

declare
l_dept pls_integer := 20;
l_nam varchar2(20);
l_loc varchar2(20);
begin
execute immediate 'select dname, loc from dept where deptno = :1'
into l_nam, l_loc
using l_dept ;
end;

参考技术A 你想知道表的列,可以
SELECT t.COLUMN_NAME FROM user_tab_columns t where t.TABLE_NAME='TABLE_NAME'追问

我最终的结果是数据,列名只是传参,这如何实现呢?

追答

这个要你循环控制了
declare curcor cu is SELECT t.COLUMN_NAME FROM user_tab_columns t where t.TABLE_NAME='TABLE_NAME';
sqlstr varchar2(100):='select ';
for c in cu
loop
if c.column_name in (x,y......)
then
sqlstr :=sqlstr||' '||c.column||','
end if;
end loop;
以上是伪代码了,大概就是这么个逻辑,你自己再改改

追问

先谢谢了,虽然我能看懂这样的逻辑,但我对存储过程不是很熟

追答

你去查查存储过程的语法吧,得自己试试,不也不知道你的情况,就算写了也不一定能用

追问

en

本回答被提问者采纳

Oracle 中的动态更新查询

【中文标题】Oracle 中的动态更新查询【英文标题】:Dynamic Update Query in Oracle 【发布时间】:2010-02-23 17:33:08 【问题描述】:

我正在尝试为表创建标准 UPDATE 查询。但是,如果满足某些条件,则应在 UPDATE 语句中包含/排除某些列。

例如:

 UPDATE TBL_PROJECT SET
     REVISION_COUNT = V_REVISION_COUNT
    ,PRIMARY_BRANCH = IN_PRIMARY_BRANCH
    ,PROJECT_STATUS = IN_PROJECT_STATUS
    ...
  WHERE PROJECT_ID = IO_PROJECT_ID
  AND   REVISION_COUNT = IO_REVISION_COUNT
  RETURNING REVISION_COUNT INTO IO_REVISION_COUNT';

但是,该表有两列供提交者和批准者使用。因此,如果状态设置为已提交或已批准,我希望更新这些列。例如。

IF IN_PROJECT_STATUS = 'SUB'
  UPDATE TBL_PROJECT SET
    SUBMITTED_DATE = SYSDATE
ELSIF IN_PROJECT_STATUS = 'APP'
  UPDATE TBL_PROJECT SET
    APPROVED_DATE = SYSDATE
END;

我还需要返回 REVISION_COUNT 和受影响的行数(rowcount)来检查更新是否成功。

编写此查询的最佳方式是什么?我假设动态查询比使用 if-elsif-else 语句更好,因为整个查询在每个块中几乎重复。

【问题讨论】:

【参考方案1】:

您可以编写一个UPDATE,并使用DECODE(或CASE)仅在in_project_status匹配时更新日期:

...
, submitted_date = DECODE( in_project_status, 'SUB', SYSDATE, submitted_date )
, approved_date  = DECODE( in_project_status, 'APP', SYSDATE, approved_date )
...

这样可以避免重复的UPDATE

【讨论】:

@Matt McCormick:在 10g 上,使用 CASE 而不是 DECODE【参考方案2】:

案例示例:

UPDATE TBL_PROJECT 
  SET REVISION_COUNT = v_revision_count,
      PRIMARY_BRANCH = IN_PRIMARY_BRANCH,
      PROJECT_STATUS = IN_PROJECT_STATUS
      ...
      SUBMITTED_DATE = CASE WHEN IN_PROJECT_STATUS = 'APP' THEN SYSDATE ELSE SUBMITTED_DATE END,
      APPROVED_DATE = CASE WHEN IN_PROJECT_STATUS = 'SUB' THEN SYSDATE ELSE APPROVED_DATE END,
WHERE PROJECT_ID = IO_PROJECT_ID
  AND REVISION_COUNT = IO_REVISION_COUNT
RETURNING REVISION_COUNT INTO IO_REVISION_COUNT

【讨论】:

以上是关于如何用oracle动态查询一张表里面的某些列?的主要内容,如果未能解决你的问题,请参考以下文章

【求助】有关oracle 动态行转列

Oracle 中的动态更新查询

Oracle/SQL - 基于参数的动态列

java web 中如何用一个动态的table表接受数据库中的数据

给DBGrid动态赋值后,如何用程序指定某行某列为当前焦点?(100分)

如何用SQL代码将动态查询结果赋值给变量?