Câu trả lời ngắn gọn, không.
Câu trả lời dài hơn một chút là gần.
Nó chỉ xuất hiện rằng kết quả thu được từ mỗi câu lệnh là giống hệt nhau. Nếu chúng tôi sử dụng hàm DUMP để đánh giá các loại dữ liệu được trả về, bạn sẽ thấy ý tôi là:
SQL> select dump(case 1 when 2 then null else 0 end) as simple_case
2 , dump(case when 1 = 2 then null else 0 end) as searched_case
3 , dump(decode(1, 2, null, 0)) as decode
4 from dual;
SIMPLE_CASE SEARCHED_CASE DECODE
------------------ ------------------ -----------------
Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=1 Len=1: 48
SQL Fiddle
Bạn có thể thấy rằng kiểu dữ liệu của DECODE là 1, trong khi hai câu lệnh CASE "trả về" kiểu dữ liệu là 2. Sử dụng Tóm tắt kiểu dữ liệu của Oracle, DECODE trả về một VARCHAR2 (kiểu dữ liệu 1) trong khi câu lệnh CASE "trả về "số (kiểu dữ liệu 2).
Tôi giả sử điều này xảy ra bởi vì, như tên gợi ý, DECODE là một chức năng và CASE thì không, có nghĩa là chúng đã được triển khai khác nhau trong nội bộ. Không có cách thực sự nào để chứng minh điều này.
Bạn có thể nghĩ rằng điều này không thực sự ảnh hưởng đến bất cứ điều gì. Nếu bạn cần nó là một số thì Oracle sẽ ngầm chuyển ký tự thành một số theo quy tắc chuyển đổi ngầm, phải không? Điều này cũng không đúng, nó sẽ không hoạt động trong UNION vì các loại dữ liệu có giống hệt nhau; Oracle sẽ không thực hiện bất kỳ chuyển đổi ngầm nào để khiến mọi thứ trở nên dễ dàng với bạn. Thứ hai, đây là những gì Oracle nói về chuyển đổi ngầm:
Oracle khuyên bạn nên chỉ định các chuyển đổi rõ ràng, thay vì dựa vào các chuyển đổi ngầm hoặc tự động, vì những lý do sau:
Các câu lệnh SQL dễ hiểu hơn khi bạn sử dụng các hàm chuyển đổi kiểu dữ liệu rõ ràng.
Chuyển đổi kiểu dữ liệu ngầm định có thể có tác động tiêu cực đến hiệu suất, đặc biệt nếu kiểu dữ liệu của giá trị cột được chuyển đổi thành giá trị của một hằng số thay vì ngược lại.
Chuyển đổi ngầm định phụ thuộc vào ngữ cảnh mà nó xảy ra và có thể không hoạt động theo cách giống nhau trong mọi trường hợp. Ví dụ:chuyển đổi ngầm định từ giá trị ngày giờ thành giá trị VARCHAR2 có thể trả về một năm không mong muốn tùy thuộc vào giá trị của tham số NLS_DATE_FORMAT.
Các thuật toán để chuyển đổi ngầm có thể thay đổi giữa các bản phát hành phần mềm và giữa các sản phẩm của Oracle. Hành vi của các chuyển đổi rõ ràng dễ dự đoán hơn.
Đó không phải là một danh sách đẹp; nhưng điểm áp chót mang lại cho tôi những cuộc hẹn hò một cách tuyệt vời. Nếu chúng tôi sử dụng truy vấn trước đó và chuyển đổi nó thành truy vấn sử dụng ngày thay thế:
select case sysdate when trunc(sysdate) then null
else sysdate
end as simple_case
, case when sysdate = trunc(sysdate) then null
else sysdate
end as searched_case
, decode(sysdate, trunc(sysdate), null, sysdate) as decode
from dual;
Một lần nữa, sử dụng DUMP trên truy vấn này, các câu lệnh CASE trả về kiểu dữ liệu 12, một DATE. DECODE đã chuyển đổi sysdate
thành một VARCHAR2.
SQL> select dump(case sysdate when trunc(sysdate) then null
2 else sysdate
3 end) as simple_case
4 , dump(case when sysdate = trunc(sysdate) then null
5 else sysdate
6 end) as searched_case
7 , dump(decode(sysdate, trunc(sysdate), null, sysdate)) as decode
8 from dual;
SIMPLE_CASE
----------------------------------
Typ=12 Len=7: 120,112,12,4,22,18,7
SEARCHED_CASE
----------------------------------
Typ=12 Len=7: 120,112,12,4,22,18,7
DECODE
----------------------------------
Typ=1 Len=19: 50,48,49,50,45,49,50,45,48,52,32,50,49,58,49,55,58,48,54
SQL Fiddle
Lưu ý (trong SQL Fiddle) rằng DATE đã được chuyển đổi thành một ký tự bằng cách sử dụng phiên NLS_DATE_FORMAT.
Có một ngày được chuyển đổi hoàn toàn thành một VARCHAR2 có thể gây ra sự cố. Nếu bạn có ý định sử dụng TO_CHAR, để chuyển đổi ngày của bạn thành một ký tự, truy vấn của bạn sẽ bị phá vỡ ở chỗ bạn không mong đợi.
SQL> select to_char( decode( sysdate
2 , trunc(sysdate), null
3 , sysdate )
4 , 'yyyy-mm-dd') as to_char
5 from dual;
select to_char( decode( sysdate
*
ERROR at line 1:
ORA-01722: invalid number
SQL Fiddle
Tương tự, số học ngày tháng không còn hoạt động nữa:
SQL>
SQL>
SQL> select decode(sysdate, trunc(sysdate), null, sysdate) + 1 as decode
2 from dual;
select decode(sysdate, trunc(sysdate), null, sysdate) + 1 as decode
*
ERROR at line 1:
ORA-01722: invalid number
SQL Fiddle
Điều thú vị là DECODE chỉ chuyển đổi biểu thức thành VARCHAR2 nếu một trong các kết quả có thể là NULL. Nếu giá trị mặc định là NULL thì điều này không xảy ra. Ví dụ:
SQL> select decode(sysdate, sysdate, sysdate, null) as decode
2 from dual;
DECODE
-------------------
2012-12-04 21:18:32
SQL> select dump(decode(sysdate, sysdate, sysdate, null)) as decode
2 from dual;
DECODE
------------------------------------------
Typ=13 Len=8: 220,7,12,4,21,18,32,0
SQL Fiddle
Lưu ý rằng DECODE đã trả về kiểu dữ liệu là 13. Điều này không được lập thành văn bản nhưng tôi giả sử là một kiểu ngày như số học ngày tháng, v.v. hoạt động.
Tóm lại, hãy tránh DECODE nếu bạn có thể; bạn có thể không nhất thiết phải nhận được các loại dữ liệu mà bạn mong đợi. Để trích dẫn Tom Kyte:
Giải mã hơi tối nghĩa - CASE rất rõ ràng. Những điều dễ thực hiện trong giải mã sẽ dễ thực hiện trong CASE, những điều khó hoặc không thể thực hiện được với giải mã lại dễ thực hiện trong CASE. Về mặt logic, CASE sẽ thắng.
Để hoàn thiện, có hai chức năng sự khác biệt giữa DECODE và CASE.
- Không thể sử dụng DECODE trong PL / SQL.
-
Không thể sử dụng CASE để so sánh trực tiếp các giá trị rỗng
SQL> select case null when null then null else 1 end as case1 2 , case when null is null then null else 1 end as case2 3 , decode(null, null, null, 1) as decode 4 from dual 5 ; CASE1 CASE2 DECODE ---------- ---------- ------ 1
SQL Fiddle