2013-04-02 45 views
5

Trong oracle SQL, tôi yêu cầu chọn một hàng nếu chỉ có một hàng, nếu có nhiều hàng hơn, nên chọn 0 hàng.Cách chọn bản ghi nếu truy vấn trả về một hàng hoặc chọn không có bản ghi nếu truy vấn trả về nhiều hàng hơn

+0

Bạn chọn hàng như thế nào? Bạn có viết một chương trình chọn smth từ một số bảng không? Điều gì trả về 0 bản ghi? Bạn có nghĩa là một số chức năng trả về 0? Bạn đang sử dụng PL/SQL hay SQL chỉ? Đây là lý do tại sao bạn có câu trả lời lộn xộn ... – Art

Trả lời

5

Nếu bạn đang sử dụng PL/SQL, sau đó chọn cột sử dụng select-into sẽ ném một ngoại lệ too_many_rows nếu có nhiều hơn một dòng trả về:

declare 
    var table.column%type; 
begin 
    select column 
    into var 
    from table 
    where ...; 
end; 

Nếu bạn muốn làm điều này chỉ bằng cách sử dụng SQL, sau đó bạn có thể làm điều gì đó như:

select * 
from 
    (select s.*, count(*) over() c 
    from 
    (select * 
    from table 
    where ... 
    and rownum <= 2 
    ) s 
) 
where c = 1 

CẬP NHẬT

Vì lý do này, lý do hạn chế rownum <= 2 là rút ngắn truy vấn nếu có nhiều hơn 2 hàng trong tập hợp kết quả. Điều này có thể mang lại lợi ích hiệu suất đáng kể nếu tập dữ liệu lớn.

+0

Tôi tìm thấy những gì tôi đang tìm kiếm, cảm ơn. Nhưng ở đây, nó sẽ hoạt động mà không có truy vấn con 'rownum <= 2'. –

+0

Sử dụng mệnh đề 'over()' bên dưới sql có thể hoạt động. 'SELECT * FROM (SELECT COUNT (*) trên() cnt, fld1, fld2 FROM tbl1) WHERE cnt = 1' –

+5

@StalinGino lý do Chris đặt' rownum <= 2' là để thực hiện. tức là chỉ tính hai hàng tối đa (nếu không, nếu bạn truy vấn phù hợp với hàng triệu hàng, bạn sẽ yêu cầu Oracle tính tất cả các hàng và sau đó loại bỏ tất cả nếu bạn có 2 hàng trở lên sẽ mất nhiều thời gian hơn). – DazzaL

-1

Hãy thử điều này:

SELECT col1, col2 FROM 
(SELECT count(id) as 'cnt', col1, col2 FROM table_name WHERE col1='value') 
WHERE cnt=1; 
+0

Tôi nghĩ rằng asterix không cho phép bạn trộn nó với bất kỳ cột/chức năng nào khác. * Chọn *, đếm (id) * sẽ không hoạt động –

+0

có, true..lets thay thế bằng tên col ... Cảm ơn :) –

+1

count() là một hàm tổng hợp, nó sẽ không cho phép chúng tôi thêm * hoặc khác cột trừ khi được chỉ định trong nhóm theo biểu thức. điều này sẽ không hoạt động. Khi sử dụng 'count (*) over()' được nói trong câu trả lời khác, nó sẽ làm việc –

-1

DECLARE COL_COUNT NUMBER;
BEGIN
COL_COUNT: = 0;
CHỌN COUNT (1) INTO COL_COUNT FROM USER_TAB_COLUMNS WHERE TABLE_NAME = '(tên bảng ur)';
NẾU COL_COUNT = 0 THEN
THỰC HIỆN NGAY LẬP TỨC ('select * from dual');
END IF;
END;

+0

Im không tìm kiếm mã sql pl. Theo cách đơn giản, tôi có thể sử dụng hàm đếm như 'select * từ bảng trong đó x = y và (select count (*) từ bảng x = y) = 1', không cần plsql cho –

2

tôi đã đưa ra với điều này, chỉ dành riêng cho các heck của nó, sử dụng một CTE

With counter as 
(select count(any_field) as cnt from your_query 
) 
SELECT 
    your_query 
WHERE exists (SELECT cnt from Counter WHERE cnt=1) 

1 hàng khi có 1 kỷ lục - http://sqlfiddle.com/#!4/84c7b/2
0 hàng khi hơn 1 rec - http://sqlfiddle.com/#!4/95c4a/1

EDIT
hoặc nếu bạn muốn tránh lặp lại toàn bộ truy vấn ... ví dụ:
(sử dụng giản đồ từ sqlfiddle http://sqlfiddle.com/#!4/6a2d8/117)

With results as 
(select * from montly_sales_totals 
), 
counter as 
(SELECT count(name) as cnt FROM results 
) 
SELECT * 
FROM results 
WHERE exists (SELECT cnt from Counter WHERE cnt=5) 
+0

Tôi có thể nói như vậy , 'select * từ bảng trong đó x = y và (select count (*) từ bảng trong đó x = y) = 1' là tốt hơn :) –

+0

ok, được chỉnh sửa để hiển thị cách tránh lặp lại toàn bộ truy vấn. Tôi thích CTE :) –

1
SELECT fld1, fld2 
FROM (SELECT COUNT(*) over() cnt ,fld1, fld2 FROM tbl WHERE fld1 = 'key') 
WHERE cnt = 1 
0

tôi yêu cầu để chọn một hàng nếu có chỉ có một hàng tồn tại là, nếu có có nhiều hàng, cần chọn 0 hàng.

tôi giả sử bảng chỉ chứa hàng (s) bạn quan tâm để xem (hoặc không nhìn thấy), trong trường hợp đó tôi sẽ viết một cái gì đó giống như

select * 
    from table1 
where 1 = (select count(1) 
       from table1 
      ) 

Trong trường hợp bạn muốn xem chỉ có một hàng từ một tập hợp con của các kết quả từ bảng của bạn, tôi sẽ đi cho một cái gì đó như:

with t as (select * 
       from table1 
      where [put here your condition] 
) 
select * 
    from t 
where 1 = (select count(1) 
       from t 
      ) 
Các vấn đề liên quan