Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql oracle解码的查找表?_Sql_Oracle_Decode - Fatal编程技术网

Sql oracle解码的查找表?

Sql oracle解码的查找表?,sql,oracle,decode,Sql,Oracle,Decode,这可能是一个新手问题,但 我们都熟悉甲骨文的解码和案例,例如 select decode (state, 0, 'initial', 1, 'current', 2, 'finnal', state) from states_table 或者使用CASE的类似东西 现在让我们假设我有一个具有相同值的表: state_num | state_desc 0 | 'initial' 1

这可能是一个新手问题,但

我们都熟悉甲骨文的解码和案例,例如

select
  decode (state,
          0, 'initial',
          1, 'current',
          2, 'finnal',
          state)
from states_table
或者使用CASE的类似东西

现在让我们假设我有一个具有相同值的表:

state_num | state_desc
        0 | 'initial'
        1 | 'current'
        2 | 'finnal'
是否有一种方法可以使用此表作为解码的资源来执行相同的查询?
请注意,我不想连接该表以访问另一个表中的数据。。。我只是想知道是否有什么东西可以用来进行某种
解码(myField,使用IsLookuptable,thisValueForDefault)
不,除了使用第二个表的联接之外,没有其他方法。当然,可以在select子句中编写标量子查询,也可以编写自己的函数,但这样做效率低下

如果需要表中的数据,则需要从中进行选择

编辑: 我必须改进我先前关于这种低效做法的陈述

在选择列表中使用标量子查询时,您可能希望强制执行一个嵌套的类似循环的计划,其中标量子查询针对states_表的每一行执行。至少我预料到:-)

然而,Oracle已经实现了标量子查询缓存,这导致了一个非常好的优化。它只执行子查询3次。有一篇关于标量子查询的优秀文章,在这篇文章中,您可以看到更多的因素在这种优化行为中发挥作用:

这里是我自己的测试,看看这在工作。为了模拟您的表,我使用了以下脚本:

create table states_table (id,state,filler)
as
 select level
      , floor(dbms_random.value(0,3))
      , lpad('*',1000,'*')
   from dual
connect by level <= 100000
/
alter table states_table add primary key (id)
/
create table lookup_table (state_num,state_desc)
as
select 0, 'initial' from dual union all
select 1, 'current' from dual union all
select 2, 'final' from dual
/
alter table lookup_table add primary key (state_num)
/
alter table states_table add foreign key (state) references lookup_table(state_num)
/
exec dbms_stats.gather_table_stats(user,'states_table',cascade=>true)
exec dbms_stats.gather_table_stats(user,'lookup_table',cascade=>true)
现在对标量子查询变量执行相同的操作:

SQL> select /*+ gather_plan_statistics */
  2         s.id
  3       , s.state
  4       , ( select l.state_desc
  5             from lookup_table l
  6            where l.state_num = s.state
  7         )
  8    from states_table s
  9  /

        ID      STATE (SELECT
---------- ---------- -------
         1          2 final
...
    100000          0 initial

100000 rows selected.

SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'))
  2  /

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  22y3dxukrqysh, child number 0
-------------------------------------
select /*+ gather_plan_statistics */        s.id      , s.state      , ( select l.state_desc
 from lookup_table l           where l.state_num = s.state        )   from states_table s

Plan hash value: 2600781440

---------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
---------------------------------------------------------------------------------------------------------------
|   1 |  TABLE ACCESS BY INDEX ROWID| LOOKUP_TABLE |      3 |      1 |      3 |00:00:00.01 |       5 |      0 |
|*  2 |   INDEX UNIQUE SCAN         | SYS_C0040786 |      3 |      1 |      3 |00:00:00.01 |       2 |      0 |
|   3 |  TABLE ACCESS FULL          | STATES_TABLE |      1 |  99614 |    100K|00:00:00.30 |   20012 |   9367 |
---------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("L"."STATE_NUM"=:B1)


20 rows selected.
请看步骤1和步骤2的“开始”列:仅3

在您的情况下,这种优化是否总是一件好事取决于许多因素。您可以参考前面提到的文章来了解一些方法的效果

在只有三种状态的情况下,标量子查询变量似乎不会出错

问候,,
Rob.

您可以使用子查询代替联接,即

select nvl(
   (select state_desc 
   from lookup 
   where state_num=state),to_char(state)) 
from states_table;

是的,伙计。。正如我在“请注意,我不想连接表以访问另一个表中的数据…”中所强调的那样,这正是我不想要的。情况是,我被困在一个系统中,该系统允许我为我想要的每个字段输入参数,但不允许我编辑查询的其余部分。这就是为什么我可以使用解码,但不能使用连接。-1表示“低效练习”。在实践中,开销非常小,值得与代码的可理解性进行权衡,这是一个巨大的好处。关于关系数据库中的enum支持,已经有很多讨论了——尝试一下谷歌,让它混合了知情和有缺陷的讨论。没错,这是可能的。但这是不可取的。不过,我会改写我的答案:-)这样就行了。我不太熟悉这种做法的利弊权衡,但如果我处理的一个小问题是大规模解码将使其变得非常混乱:(@ammoQ,你对默认值有什么建议吗?干杯!编辑:再多提供一点默认值Rob van Wijk:建议与否…不要太迂腐。如果它能工作并且足够快,那么它就足够好了。子查询不一定慢,这取决于oracle执行联接的方式。我在这里运行了一个小测试,使用一个较小的查找表和一个较大的其他表,这两种方法在这个设置中速度相同
select nvl(
   (select state_desc 
   from lookup 
   where state_num=state),to_char(state)) 
from states_table;