Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

mệnh đề liên hiệp trong sql

Câu trả lời này có thể hơi lan man ...

Oracle là rất cầu kỳ với các hoạt động thiết lập. Mỗi cột phải có cùng kiểu dữ liệu với các cột tương ứng trong các truy vấn thứ hai, thứ ba, v.v..

Tôi nghĩ rằng truy vấn thứ hai của bạn không thành công vì Oracle đánh giá to_number() như một số trước để thực hiện union nhưng đánh giá nó là "null-ness" after . Truy vấn đầu tiên của bạn thành công vì giá trị đầu tiên đã được đánh giá cho "null-ness" và sau đó là union xảy ra. Điều này ngụ ý rằng thứ tự đánh giá là:

  1. Các chức năng được lựa chọn đầu tiên
  2. Loại dữ liệu được chọn đầu tiên
  3. Chức năng lựa chọn thứ hai
  4. công đoàn
  5. Loại dữ liệu được lựa chọn thứ hai

Tôi sẽ cố gắng chứng minh điều này từng bước nhưng tôi không chắc nó sẽ trở thành bằng chứng tuyệt đối.

Cả hai truy vấn sau đây

select 1 from dual union select '1' from dual;
select '1' from dual union select 1 from dual;

sẽ không thành công với lỗi sau vì không có chuyển đổi ngầm định nào diễn ra.

Tuy nhiên, cả hai cách sau sẽ thành công

select null from dual union select '1' from dual;
select null from dual union select 1 from dual;

Nếu chúng tôi chọn dump trong số hai truy vấn này, kết quả sau sẽ được trả về:

SQL> select dump(a)
  2    from ( select null a from dual union select '1' from dual );

DUMP(A)
-------------------------------------------------------------------

Typ=96 Len=1: 49
NULL

SQL> select dump(a)
  2    from ( select null a from dual union select 1 from dual );

DUMP(A)
-------------------------------------------------------------------

Typ=2 Len=2: 193,2
NULL

Như bạn có thể thấy, các cột có kiểu dữ liệu khác nhau . Truy vấn đầu tiên, với một ký tự, trả về một char và thứ hai trả về một số, nhưng thứ tự đã được xoay chuyển, với select thứ hai đến trước.

Cuối cùng, nếu chúng ta xem xét dump truy vấn đầu tiên của bạn

SQL> select substr(dump(ename),1,35) a, substr(dump(loc),1,35) b
  2    from ( select ename,to_number(null) as loc from emp
  3            union
  4           select to_char(null),loc from dept
  5                  );

A                                   B
----------------------------------- -----------------------------------
Typ=1 Len=6: 104,97,104,97,104,97   NULL
NULL                                Typ=1 Len=6: 104,97,104,97,104,97

SQL>

Bạn có thể thấy rằng dump(to_number(null)) là null; nhưng một varchar2 không phải là char đang được trả về, vì đây là kiểu dữ liệu của cột của bạn. Thật thú vị khi lưu ý rằng thứ tự của các câu lệnh trả về không bị đảo ngược và nếu bạn tạo truy vấn này dưới dạng bảng thì cả hai cột sẽ là varchar2 .

Khi quyết định kiểu dữ liệu của một cột trong một truy vấn chọn, Oracle sẽ lấy kiểu dữ liệu đã biết đầu tiên và sau đó sử dụng kiểu dữ liệu đó để tính toán kiểu dữ liệu tổng thể. Đây sẽ là lý do tại sao các truy vấn trong đó select đầu tiên là null khi các hàng của họ bị đảo ngược.

Truy vấn đầu tiên của bạn thành công vì lần chọn đầu tiên, select ename,to_number(null) from emp , "mô tả" tập kết quả sẽ trông như thế nào. |varchar2|null| . Sau đó, truy vấn thứ hai thêm, |varchar2|varchar2| , không gây ra vấn đề gì.

Truy vấn thứ hai của bạn không thành công vì lần chọn đầu tiên select ename,to_number(null) from emp "mô tả" kết quả được đặt là varchar2, null . Tuy nhiên, sau đó bạn cố gắng thêm một số null và một varchar2 trong union .

Bước nhảy vọt của niềm tin ở đây là Oracle đang quyết định rằng to_number(null) là một số trước tới union và không đánh giá nó cho "null-ness" cho đến sau đó. Tôi thực sự không biết cách kiểm tra xem điều này có thực sự xảy ra hay không vì bạn không thể tạo một đối tượng có null và như bạn lưu ý, bạn cũng không thể chọn nó.

Vì tôi không thể chứng minh điều gì đó mà Oracle không cho phép, tôi sẽ cố gắng tìm bằng chứng thực nghiệm. Xem xét kết quả (hoặc lỗi) của các truy vấn sau.

SQL> select 1 as a from dual union select to_number(null) from dual;

         A
----------
         1


SQL> select '1' as a from dual union select to_number(null) from dual;
select '1' as a from dual union select to_number(null) from dual
       *
ERROR at line 1:
ORA-01790: expression must have same datatype as corresponding expression


SQL> select 1 as a from dual union select to_char(null) from dual;
select 1 as a from dual union select to_char(null) from dual
       *
ERROR at line 1:
ORA-01790: expression must have same datatype as corresponding expression


SQL> select '1' as a from dual union select to_char(null) from dual;

A
-
1

Chúng dường như chứng minh rằng to_charto_number , cho dù chúng được thực hiện trên null hay không, xác định ngầm một kiểu dữ liệu mà sau đó sẽ được đánh giá về tính phù hợp của nó trong một union , trước khi họ đánh giá "null-ness"

Giải thích này cũng sẽ bao gồm coalesce vấn đề dưới dạng to_number(null) là một số trước nó là một null.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tạo bộ hẹn giờ trong Oracle Forms / Forms 6i và hiển thị đồng hồ

  2. Lỗi Oracle .Net ManagedDataAccess:Không thể tải loại 'OracleInternal.Common.ConfigBaseClass' từ lắp ráp

  3. Tôi không thể sử dụng biến ràng buộc trong datagrip

  4. PLS-00386:loại không khớp được tìm thấy giữa con trỏ FETCH và các biến INTO

  5. Oracle 11g Express Edition dành cho Windows 64bit?