2012-01-18 29 views
6

Với DBI có cách nào để xác định xem một câu lệnh xử lý được thực hiện cho câu lệnh SELECT có trả về bất kỳ hàng nào mà không tìm nạp từ nó không?

I.e. cái gì đó như:

use DBI; 
... 
my $sth = $dbh->prepare("SELECT ..."); 
$sth->execute; 

if (..$sth will return at least one row...) { 
    ... 
} else { 
    ... 
} 

và tôi muốn thực hiện các thử nghiệm $sth will return at least one rowmà không thực hiện bất kỳ lấy phương pháp trên $sth.

Lưu ý - Tôi không cần số lượng chính xác của hàng (ví dụ: $sth->rows), tôi chỉ cần biết nếu $sth->rows sẽ> 0.

Trả lời

8

$ sth-> hàng vẫn là lựa chọn tốt nhất của bạn. Như bạn đã nói, chỉ cần kiểm tra xem nó có lớn hơn 0.

if ($sth->rows > 0){ 
    # magic here! 
} 

EXCEPT! tài liệu DBI cho biết điều này không đáng tin cậy đối với các số liệu thống kê được chọn cho đến khi tất cả các hàng đã được tìm nạp. Không có cách nào để xác định số lượng hàng sẽ được tìm nạp trước. Nếu bạn cần biết điều này, lời khuyên đầu tiên là làm một số

select count(*) from <table> 

Xem this section of the DBI documentation.

+0

Nó có thể không làm việc tùy thuộc vào trình điều khiển, ví dụ với DBD :: Oracle, $ sth-> rows trả về số hàng bị ảnh hưởng chỉ cho các cập nhật, xóa và chèn nhưng -1 cho các lựa chọn (http://search.cpan.org/~pythian/DBD-Oracle-1.74/lib/DBD/Oracle.pm# hàng) – Fred

1

Thay vì tìm nội dung nào đó trong DBI, bạn có thể sử dụng SQL cho điều đó. Chỉ cần quấn CHỌN vào một SELECT với EXISTS điều kiện:

SELECT 1 FROM DUAL WHERE EXISTS (SELECT ...); 

Nó không phải SQL cầm tay: FROM DUAL có thể trông khác trên RDBMS của bạn, DB của bạn có thể không hỗ trợ EXISTS và truy vấn con. Tuy nhiên, hầu hết các DB hiện đại cho phép bạn nấu một cái gì đó như thế này.

Nó phải là cách hiệu quả nhất như tối ưu hóa có thể bỏ qua bỏ qua thứ tự của nhóm bằng cách, giới hạn về truy vấn phụ. Kiểm tra kế hoạch thực hiện.

SELECT COUNT(*) FROM (SELECT ...) 

Cũng có thể, nhưng DB phải kiểm tra toàn bộ tập dữ liệu để giúp bạn có chính xác số hàng.

Nếu bạn kiểm soát xây dựng SQL sau đó bạn có thể thả tự do, nhóm bằng (chỉ nếu không có có một phần cũng) và áp dụng giới hạn trên đó để chọn chỉ có một hàng.

0

Có thể đây là những gì bạn đang tìm kiếm.

"Active" (boolean, read-only)

Các "Active" thuộc tính là true nếu đối tượng xử lý là "hoạt động". Điều này hiếm khi được sử dụng trong các ứng dụng. Ý nghĩa chính xác của hoạt động là hơi mơ hồ vào lúc này. Đối với một cơ sở dữ liệu xử lý nó thường nghĩa là xử lý được kết nối với một cơ sở dữ liệu ("$ dbh-> ngắt kết nối" đặt "Active" off). Để xử lý câu lệnh, điều này thường có nghĩa là tay cầm là "CHỌN" có thể có nhiều dữ liệu hơn để tìm nạp. (Tìm nạp tất cả dữ liệu hoặc gọi "$ sth-> finish" đặt "Đang hoạt động".)

+0

No. Khi bạn trích dẫn câu trả lời, 'Hoạt động' thường có nghĩa là một lệnh xử lý * có thể * có nhiều hàng hơn để tìm nạp. Vì vậy, ngay cả một câu lệnh được thực hiện mà chúng ta biết * một tiên * sẽ không trả lại hàng nào (dưới các trình điều khiển điển hình như 'DBD :: mysql') báo cáo' Hoạt động' cho đến khi 'first' (và final)' fetch() 'được gọi. – pilcrow

2

Tôi không nghĩ có cách nào đáng tin cậy để kiểm tra xem có thể tìm nạp bất kỳ hàng nào ngoài tìm nạp chúng không. Tất nhiên khi bạn đã tìm nạp hàng đầu tiên, nó không có sẵn để tìm nạp, và bạn phải giữ nó "trong tay". Nhưng điều này không quá khó để giải quyết.

Tôi thường sẽ nghĩ đến sử dụng thành ngữ như một trong hai sau đây:

... 
$sth->execute; 

my @rows; 

my $row = $sth->fetchrow_hashref(); 

if ($row) { 
    do { 
     # do something with $row 
     ... 

     $row = $sth->fetchrow_hashref(); 
    } while ($row); 
} else { 
    # No rows 
} 

hoặc

... 
$sth->execute; 

my @rows; 

while (my $row = $sth->fetchrow_hashref()) { push @rows, $row } 

if (@rows) { 
    # Some rows, now in @rows 
} else { 
    # No rows 
} 
+0

Hoặc chỉ sử dụng '$ sth-> fetchall_arrayref()' trực tiếp như được mô tả trong https://stackoverflow.com/a/47679059/111036 nếu kết quả mong đợi sẽ có kích thước hợp lý. – mivk

Các vấn đề liên quan