English 中文(简体)
oracle:你能跨表使用DECODE吗?
原标题:oracle: can you use DECODE across tables?

这个函数很新,但据我所知,DECODE根据另一个指定值(arg2)测试指定的属性(arg1),如果它们匹配,它将显示结果(arg3);否则,如果不匹配,则显示默认值(arg4)

DECODE(firstname, John , last is doe , I don t know the last name )

您可以使用另一个表中的数据来模拟联接吗?喜欢

DECODE(publisherid, publisher.pubid, publisher.name, unknown )

我在试,但不起作用。不知道这是否可能,或者我只是做错了。有什么想法吗?

最佳回答

11g文档声明搜索参数可以是一个表达式,所以您所拥有的应该有效。如果您遇到ORA错误,您应该告诉我们。否则,很可能您没有匹配的数据,或者publisher.name列为null。。。

您不会使用它来模拟联接——您仍然希望实际适当地联接(ANSI 89或92语法,但最好是92)表,否则您将处理笛卡尔乘积中的许多垃圾行,然后DECODE将在这些垃圾行上执行。

除非你在9i之前(8.1.6,根据Ask Tom),我不会在DECODE上浪费你的时间,而是使用ANSI CASE语句:

CASE 
  WHEN publisherid = publisher.pubid THEN publisher.name
  ELSE  unknown 
END
问题回答

您可以在不同表的列之间使用它,如下所示:

select oi.order_id, oi.product_id, oi.unit_price, p.list_price, 
       decode(oi.unit_price, p.list_price,  No Discount ,
                   p.list_price - oi.unit_price||  discount ) disc
from demo_ord_items oi 
  join demo_product_info p on p.product_id = oi.product_id
where oi.order_id = 1

理论上,可以将其用作联接条件

select oi.order_id, oi.product_id, oi.unit_price, p.list_price
from demo_ord_items oi 
  join demo_product_info p on p.product_id = oi.product_id 
                            and decode(oi.unit_price, p.list_price,0,1) = 1
where oi.order_id = 1

但这并不常见。条件是布尔值(true/false),解码返回一个数字或字符,因此解码有点多余(或者可能会重写以更清晰)。

就语法而言,你说得对。如果结果总是未知,请输出publisherid并检查表中是否有它。

如果ID-s是文本字段,请注意解码区分大小写。还要检查你是否在某个地方修剪了id。

当以下任何一项为真时,请使用DECODE

  • You want to write non-portable SQL
  • You want to to write code that only Oracle developers recognize and understand
  • You want to write code that is hard to read
  • You want to increase the chance of introducing bugs the next time you change the code
  • You want the optimizer to generate suboptimal execution plans (when used in where-clause).
  • You are writing throw-away code

简而言之,根本不要使用DECODE。没有什么是用CASE/WHEN做不到的。是的,在键盘上会有更多的打字,这是“值得的”。

话虽如此,当我总是喜欢DECODE时,有一种情况是一次性的,那就是它如何处理NULL。这种情况是,当我有两个(希望)相同的表,具有相同的键,并且我想找出是否有任何行两个表在列值上不一致。

例如,假设您出于性能原因重写了批处理过程,并且希望确保新版本产生与旧版本相同的结果。在这种情况下,您会认为NULLNULL是相同的“值”DECODE的行为恰好就是这样。

decode(a, b,  Y ,  N ) 

将转换为以下case/when构造

case when a = b then  Y 
     when a is null and b is null then  Y 
     else  N 
 end  

以下是我的意思的一个例子

with old_table as(
  select 1 as id,  A   as old_col from dual union all
  select 2 as id,  A   as old_col from dual union all
  select 3 as id,  A   as old_col from dual union all
  select 4 as id, null as old_col from dual
)
,new_table as(
  select 1 as id,  A    as new_col from dual union all
  select 2 as id,  B    as new_col from dual union all
  select 3 as id, null  as new_col from dual union all
  select 4 as id, null  as new_col from dual
)
select id
      ,old_col
      ,new_col
      ,decode(old_col, new_col,  Y ,  N ) as has_same_val
  from old_table 
  join new_table using(id);

ID OLD_COL NEW_COL HAS_SAME_VAL
-- ------- ------- ------------
 1 A       A       Y
 2 A       B       N
 3 A       null    N            <-- Note those
 4 null    null    Y            <-- two cases

因此,为了找到不同之处,我会这样做:

where decode(old_col1, new_col1,  same ,  diff ) =  diff 
   or decode(old_col2, new_col2,  same ,  diff ) =  diff 
   or decode(old_col3, new_col3,  same ,  diff ) =  diff 
   or decode(old_col4, new_col4,  same ,  diff ) =  diff 
   or decode(old_col5, new_col5,  same ,  diff ) =  diff 




相关问题
Export tables from SQL Server to be imported to Oracle 10g

I m trying to export some tables from SQL Server 2005 and then create those tables and populate them in Oracle. I have about 10 tables, varying from 4 columns up to 25. I m not using any constraints/...

Connecting to Oracle 10g with ODBC from Excel VBA

The following code works. the connection opens fine but recordset.recordCount always returns -1 when there is data in the table. ANd If I try to call any methods/properties on recordset it crashes ...

How to make a one to one left outer join?

I was wondering, is there a way to make a kind of one to one left outer join: I need a join that matches say table A with table B, for each record on table A it must search for its pair on table B, ...

Insert if not exists Oracle

I need to be able to run an Oracle query which goes to insert a number of rows, but it also checks to see if a primary key exists and if it does, then it skips that insert. Something like: INSERT ALL ...

How can I store NULLs in NOT NULL field?

I just came across NULL values in NOT-NULL fields in our test database. How could they get there? I know that NOT-NULL constraints can be altered with NOVALIDATE clause, but that would change table s ...

Type reference scope

I m studying databases and am currently working on a object-relational DB project and I ve encountered a small problem with the number of possible constraints in an object table. I m using "Database ...

OracleParameter and DBNull.Value

we have a table in an Oracle Database which contains a column with the type Char(3 Byte). Now we use a parameterized sql to select some rows with a DBNull.Value and it doesn t work: OracleCommand ...

热门标签