2012-04-03 48 views
7

Hãy bảng này WORDSOracle SQL - tìm các giá trị trong một bảng KHÔNG

WORD 
Hello 
Aardvark 
Potato 
Dog 
Cat 

Và danh sách này:

('Hello', 'Goodbye', 'Greetings', 'Dog') 

Làm thế nào để trả về một danh sách các từ mà không phải là trong từ bảng, nhưng trong danh sách của tôi?

Nếu tôi có một bảng mà "chứa tất cả các từ có thể", tôi có thể làm:

SELECT * from ALL_WORDS_TABLE 
where word in ('Hello', 'Goodbye', 'Greetings', 'Dog') 
and word not in 
(SELECT word from WORDS 
where word in ('Hello', 'Goodbye', 'Greetings', 'Dog') 
); 

Tuy nhiên tôi không có một bảng như vậy. Làm thế nào khác có thể được thực hiện?

Ngoài ra, việc xây dựng một bảng mới không phải là một tùy chọn vì tôi không có cấp truy cập đó.

Trả lời

25

Thay vì cứng mã hóa các giá trị danh sách thành hàng, sử dụng DBMS_DEBUG_VC2COLL để tự động chuyển đổi danh sách phân thành hàng, sau đó sử dụng các nhà điều hành MINUS để loại bỏ các hàng trong truy vấn thứ hai là không có trong truy vấn đầu tiên:

select column_value 
from table(sys.dbms_debug_vc2coll('Hello', 'Goodbye', 'Greetings', 'Dog')) 
minus 
select word 
from words; 
+0

Kỹ thuật tốt) Nhưng điều gì sẽ xảy ra nếu quyền truy cập vào sys. * bị từ chối? – denied

+0

@denied Vâng đó sẽ là vụng về thực sự. Có thể có các cách khác để chuyển đổi danh sách chuỗi được phân tách thành cột thanh lịch hơn sys.dbms_debug_vc2coll. Có lẽ có một giải pháp sử dụng SQL thuần túy? – Wolf

+0

@Denied Trong ngữ cảnh này, 'sys' không phải là một điều xấu. Ai đó về mặt lý thuyết có thể từ chối bạn truy cập vào loại đó, nhưng có lẽ đó không phải là điều bạn cần phải lo lắng. Đó là về khả năng là ai đó loại bỏ quyền truy cập vào 'sys.dbms_output'. –

5

Bạn có thể bật danh sách của bạn vào một cái nhìn như thế này:

select 'Hello' as word from dual 
union all 
select 'Goodbye' from dual 
union all 
select 'Greetings' from dual 
union all 
select 'Dog' from dual 

Sau đó, bạn có thể chọn từ đó:

select * from 
(
    select 'Hello' as word from dual 
    union all 
    select 'Goodbye' from dual 
    union all 
    select 'Greetings' from dual 
    union all 
    select 'Dog' from dual 
) 
where word not in (select word from words); 

Có thể không phải là một giải pháp gọn gàng như bạn có thể hy vọng ..

Bạn nói rằng bạn không có đủ đặc quyền để tạo bảng, vì vậy có lẽ bạn không thể tạo loại - nhưng nếu bạn có thể tìm thấy loại phù hợp "nằm xung quanh" trong cơ sở dữ liệu của mình, bạn có thể làm này:

select * from table (table_of_varchar2_type('Hello','Goodbye','Greetings','Dog')) 
where column_value not in (select word from words); 

Đây table_of_varchar2_type được tưởng tượng là tên của một loại được định nghĩa như sau:

create type table_of_varchar2_type as table of varchar2(100); 

Một trong những loại bạn có khả năng để có thể tìm thấy là SYS.KU$_VCNT mà là một MỤC VARCHAR2 (4000).

4

Hãy thử giải pháp này:

SELECT 
a.word 
FROM 
(
SELECT 'Hello' word FROM DUAL UNION 
SELECT 'Goodbye' word FROM DUAL UNION 
SELECT 'Greetings' word FROM DUAL UNION 
SELECT 'Dog' word FROM DUAL 
) a 
LEFT JOIN ALL_WORDS_TABLE t ON t.word = a.word 
WHERE 
t.word IS NULL 
Các vấn đề liên quan