2013-10-10 12 views
12

Tôi đang viết một SELECT truy vấn cơ bản, một cái gì đó như:Kiểm tra nếu CHỌN Trả Bất kỳ dòng trong Stored Procedure

SELECT id, pname, pnumber 
FROM tableName 
WHERE pnumber IS NOT NULL 

Tôi muốn sau đó thực hiện một INSERT bằng cách sử dụng kết quả đó SELECT như vậy:

IF {**the above SELECT query returned 0 rows**} 
BEGIN 
    INSERT INTO tableName (pname,pnumber) VALUES ('bob', '38499483') 
END 

Câu hỏi của tôi là, làm cách nào để kiểm tra **the above SELECT query returned 0 rows**?

+0

Mục đích của kiểm tra này là gì? Nếu bạn đang kiểm tra tính duy nhất, một chỉ mục duy nhất trên các cột đơn giản hơn – podiluska

Trả lời

23
IF NOT EXISTS (SELECT ...) 
BEGIN 
    INSERT ... 
END 

Bạn cũng có thể làm được điều này, nếu bạn hy vọng rằng các truy vấn thường có thể trả lại hàng (đặc biệt là rất nhiều hàng), có thể cung cấp một cơ hội tốt hơn để ngắn mạch:

IF EXISTS (SELECT ...) 
BEGIN 
    PRINT 'Do nothing.'; 
END 
ELSE 
BEGIN 
    INSERT ... 
END 

.. .số IF EXISTS sẽ trở lại ngay sau khi nó chạm vào hàng đầu tiên khớp với nhau.

Tôi không khuyên bạn chỉ sử dụng @@ROWCOUNT chỉ vì bạn sẽ phải thực hiện (và bỏ qua) toàn bộ kết quả được đặt mỗi lần.

+0

Tất nhiên, tôi nên biết điều này ... cảm ơn. – muttley91

+0

Tôi thích điều này.Thường thì các giải pháp công nghệ thấp là tốt vì chúng không phải là môi trường cụ thể. Mã SQL thường được chuyển từ SQL Server sang MySQL sang Oracle, ... –

1

bạn có thể sử dụng @@ROWCOUNT

SELECT id, pname, pnumber 
FROM tableName 
WHERE pnumber IS NOT NULL 

sau khi chọn này yêu cầu @@ROWCOUNT

IF @@ROWCOUNT = 0 
BEGIN 
    INSERT ... 
END 

Bằng cách này, bạn có thể trở lại một số dữ liệu và kiểm tra xem đó có kết quả hay không

0

Tôi có nhìn thấy mọi người có vấn đề về mẫu thiết kế với logic này.

1 - Kiểm tra sự tồn tại của bản ghi.
2 - Nếu nó không tồn tại, hãy chèn bản ghi.

Đặc biệt nếu đồng thời có hiệu lực. Tùy thuộc vào mức độ cách ly, bạn có thể có dữ liệu trùng lặp hoặc vi phạm chính.

Tại sao không đặt khóa chính trên pname và pnumber ở địa điểm đầu tiên. Tôi giả sử bạn đang nói về một bảng người.

Ví dụ của tôi.

-- 
-- Setup sample table w/data 
-- 

-- Sample table 
create table #person 
( 
    person_id int identity (1, 1), 
    person_name varchar(64) not null, 
    person_no varchar(16) not null 
); 
go 

-- primary key 
alter table #person 
    add primary key (person_no, person_name) 
go 

-- first insert works 
insert into #person (person_name, person_no) values ('bilbo', 123) 
go 

Chìa khóa để giải pháp là bẫy vi phạm chính khóa. Bỏ qua lỗi này có thể là tốt hay xấu tùy thuộc vào logic nghiệp vụ của bạn.

Tôi quyết định bỏ qua vấn đề.

-- 
-- Ignore primary key violations 
-- 

-- Try these steps 
BEGIN TRY 

    -- Second insert fails 
    insert into #person (person_name, person_no) values ('bilbo', 123) 

END TRY 

-- Error Handler 
BEGIN CATCH 

    -- Ignore PK error 
    IF ERROR_NUMBER() <> 2627 
    SELECT 
     ERROR_NUMBER() AS ErrorNumber 
     ,ERROR_SEVERITY() AS ErrorSeverity 
     ,ERROR_STATE() AS ErrorState 
     ,ERROR_PROCEDURE() AS ErrorProcedure 
     ,ERROR_LINE() AS ErrorLine 
     ,ERROR_MESSAGE() AS ErrorMessage; 
END CATCH 

Giải pháp này loại bỏ các mục trùng lặp và không báo cáo vi phạm PK.

+0

Tôi đã cố gắng CHỈ thực hiện một INSERT nếu nó không tồn tại vì tôi đã chạy vào một vấn đề postback trong ASP.NET. Vì vậy, bản ghi hiện tại có nghĩa là nó không cần phải được chèn bởi vì nó đã được ghi lại. Với điều đó đã nói, tôi sẽ đưa câu trả lời của bạn vào tài khoản trong những thay đổi thiết kế sắp tới. Cảm ơn. – muttley91

+0

Tôi có một sản phẩm của Microsoft trên một trong các máy chủ của tôi đang thực hiện cùng một logic. Nếu tồn tại, sau đó trả lại chìa khóa nếu không, chèn với khóa cập nhật. Tôi liên tục nhận được thông báo bế tắc trong hệ thống giám sát SQL Sentry của tôi. Giải pháp tôi đề xuất là ở trên, nhưng họ vẫn chưa triển khai nó! –

5

Trong MySQL để kiểm tra không. hàng được trả về bởi truy vấn chọn cuối cùng

select FOUND_ROWS(); 
Các vấn đề liên quan