2009-05-12 7 views
12

मैं पर्ल में DBI चल रहा हूँ और को समझ नहीं सकता कैसे, जब मैं एक तैयार बयान चलाने के लिए, मैं यह पता लगाने अगर लौटे पंक्ति संख्या 0.प्रक्रिया के लिए दो अलग-अलग कॉल किए बिना डीबीआई में पंक्ति गणना कैसे प्राप्त की जा सकती है?

है सकते हैं मुझे लगता है मैं अपने जबकि अंदर एक काउंटर सेट कर सकते हैं लूप जहां मैं अपनी पंक्तियां लाता हूं, लेकिन मैं उम्मीद कर रहा था कि ऐसा करने के लिए एक कम बदसूरत तरीका था।

उत्तर

9

आदेश में पता लगाने के लिए पंक्तियों परिणामस्वरूप में सेट कि वास्तव में आप दो विकल्प हैं कर रहे हैं: परिणाम सेट से अधिक

  1. select count(*)
  2. दोहराएं और पंक्तियों गिनती।

आप एक संग्रहीत प्रक्रिया है कि एक सरणी या अधिक फैंसी कुछ रिटर्न के माध्यम से कुछ जादू लागू कर सकते हैं, लेकिन अंत में उन दो चीजों में से एक होने के लिए की आवश्यकता होगी।

तो, परिणाम प्राप्त करने के लिए कोई फैंसीपेंट तरीका नहीं है। आपको बस उन्हें गिनना होगा :-)

+1

यहां की कुंजी मेरी क्या समझ में आई है कि क्या लाता है। मैंने सोचा कि यह किसी प्रकार का हैश वापस ले गया है और बस इसे फिर से चालू किया गया है, लेकिन वास्तव में, पूरी बात एक धारा है, इसलिए, आप डीबी से सीधे पंक्तियां ला रहे हैं (और कुछ लौटे ऑब्जेक्ट से नहीं), इसलिए, तैयार निष्पादन में वास्तव में कोई संकेत नहीं है कि कितनी पंक्तियां लौटाई गई हैं। –

17

का शीघ्रता से अवलोकन here के आधार पर यह है कि आप

$statement->execute($arg) 

चलाने के बाद आप पंक्ति

$statement->rows 
+0

कि वास्तव में कष्टप्रद है ... कि वास्तव में मैं कहाँ देख रहा था, लेकिन पूरी तरह से नहीं देख पाए, क्योंकि वे डाल है कि यदि ($ sth-> पंक्तियों == 0) के बाद लूप जहां वे पंक्तियों को पढ़ते हैं !! इसे पकड़ने के लिए धन्यवाद। –

+3

[http://search.cpan.org/~timb/DBI-1.608/DBI.pm#rows पीओडी] में पंक्तियों के बारे में बहुत महत्वपूर्ण चेतावनी नोट करें। – jplindstrom

+0

उह, हाँ, यह नहीं है कि आप स्पष्ट रूप से लिंक कैसे करते हैं :) – jplindstrom

0

पंक्तियाँ के माध्यम से गिनती का उपयोग कर सकते लगता है निश्चित रूप से डेटाबेस/ड्राइवर को संस्करण यह के आधार पर भिन्न है लगता है। मैं निश्चित रूप से तर्क के एक टुकड़े को देखता हूं जो अप्रत्याशित परिणामों से निपटाता है।

11

"caveat" in the documentation (एक और जवाब पर एक टिप्पणी में लिंक किया गया) महत्वपूर्ण है, और असली, सही उत्तर प्रदान करता है: आम तौर पर

, आप केवल एक गैर का चयन करने के बाद गिनती एक पंक्ति पर भरोसा कर सकते निष्पादित करें (कुछ विशिष्ट संचालन जैसे अद्यतन और हटाएं), या एक चयन कथन की सभी पंक्तियां लाने के बाद।

चयन विवरणों के लिए, आमतौर पर यह जानना संभव नहीं है कि उन्हें सभी को लाने के अलावा कितनी पंक्तियां वापस की जाएंगी। कुछ ड्राइवर अब तक की गई पंक्तियों की संख्या वापस कर देंगे, लेकिन अन्य पंक्तियां वापस आ सकती हैं जब तक कि सभी पंक्तियां नहीं लाई जातीं। इसलिए पंक्तियों के विवरण या $ डीबीआई :: पंक्तियों के चयन के साथ पंक्तियों का उपयोग करने की अनुशंसा नहीं की जाती है।

+3

तो, अब हम जानते हैं कि -> पंक्तियां प्रश्न का उत्तर नहीं है ... जवाब क्या है? उदाहरण में उल्लिखित उदाहरण में (उत्तर में मैंने शुरुआत में सही के रूप में चुना), वे एक चयन कर रहे हैं और फिर देख रहे हैं कि पंक्तियां == 0 ... तो, मैं उलझन में हूं। –

+0

दस्तावेज़ों की तरह कहते हैं, "चयन विवरणों के लिए, यह जानना संभव नहीं है कि उन्हें सभी को लाने के अलावा कितनी पंक्तियां वापस की जाएंगी।" मुख्य शब्द "आम तौर पर" होता है। कुछ इंजनों का उपयोग करने वाले कुछ डेटाबेस अलग-अलग व्यवहार कर सकते हैं। लेकिन सभी संभावित मामलों में 100% सुनिश्चित करने का एकमात्र तरीका हर पंक्ति और गिनती लाने के लिए है। –

2

इस SQL ​​समाधान को आजमाएं, गिनती वक्तव्य के साथ डेटा के लिए अपने एसक्यूएल को गठबंधन करें।

 
select null, null, null, count(*) from tablex 
union 
select foo, bar, foobar, null from tablex 

पहले बयान अपने खाली समय में गिनती recordset के बाकी के माध्यम से तो आप कर सकते हैं चक्र होगा, और पहली पंक्ति होना चाहिए (यदि नहीं तो आप इसे चारों ओर पाने के लिए द्वारा आदेश कर सकते हैं)।

1

मैंने गतिशील रूप से एक एसक्यूएल उत्पन्न किया है और इसे निष्पादित किया है। मेरे लिए select count(*) एक विकल्प प्रतीत नहीं होता है क्योंकि मुझे फिर से क्वेरी फिर से उत्पन्न करना है। निम्नलिखित दृष्टिकोण मेरे लिए साफ दिखता था। लेकिन आपको पंक्ति डेटा पुनर्प्राप्त करने के लिए एक बार फिर से $h->execute() जारी करना होगा।

$h->execute() or die "ERROR: Couldn't execute SQL statement"; 
$rowcount_ref = $h->fetchall_arrayref(0); 
$rowcount = scalar (@{$rowcount_ref}); 

- Shaakunthala

4

यह देर से एक सा है, लेकिन अगर किसी को ओरेकल का उपयोग करता है, यहाँ पसीना समाधान आता है:

SELECT 
    q.*, 
    ROWNUM DB_ROWNUM, 
    (SELECT max(ROWNUM) FROM ($sql)) DB_COUNT 
FROM 
    ($sql) q 

$ एसक्यूएल निश्चित रूप से, आपकी क्वेरी है। ओरेकल ऑप्टिमाइज़र बुद्धिमान है कि सब कुछ दो बार निष्पादित न करें।

अब प्रत्येक fetched पंक्ति में वर्तमान पंक्ति संख्या (पेजिंग ग्रिड पंक्ति संख्या के लिए उपयोगी) DB_ROWNUM में और DB_COUNT में पंक्तियों की पूरी संख्या है। तुम अब भी कम से कम एक पंक्ति लाने के लिए है (इसलिए यह ऊपर सवाल का जवाब बिल्कुल नहीं है;)), लेकिन पसीना उपयोग अगले आता है:

यह भी एक बहुत ही आसान तरीके से शुरू करना करने के लिए और Oracle में सीमा है और अभी भी पंक्तियों की पूरी नंबर मिल:

SELECT * FROM (
    SELECT /*+ FIRST_ROWS($limit) */ 
    q.*, 
    ROWNUM DB_ROWNUM, 
    (SELECT max(ROWNUM) FROM ($sql)) DB_COUNT 
    FROM 
    ($sql) q 
    WHERE 
    ROWNUM <= $limit 
) 
WHERE 
    DB_ROWNUM > $start 
इस के साथ

, आप वास्तव में केवल पंक्ति 51 100 करने के लिए अपने ग्रिड में दूसरे पृष्ठ के लिए प्राप्त कर सके, लेकिन अभी भी वास्तविक पंक्ति संख्या (1 से शुरू) और है प्रत्येक प्राप्त पंक्ति में पूर्ण गणना (शुरुआत और सीमा के बिना)।

+4

क्या आपका मतलब पसीना या मीठा है? –

2

CPAN का कहना है:

[...] या एक SELECT कथन की सभी पंक्तियों को लाते समय के बाद।

तो कुछ इस तरह कर रही है शायद काम करेगा:

$sth->execute() or die $sth->errstr(); 
my $hasref = $sth->fetchall_hashref('id'); 
say "There is/are " . scalar(keys(%{$hasref}) . " row(s)."; 
0

आप को पता है कि कितने पंक्तियों उन सभी के माध्यम से चलने से पहले देखते हैं चाहते हैं, एक MySQL विशेष समाधान FOUND_ROWS() हो सकता है।

अपनी पहली क्वेरी में, SELECT के ठीक बाद जोड़ें। फिर SELECT FOUND_ROWS(); करें, और आपके पास तुरंत पंक्ति गणना तक पहुंच है। अब आप तय कर सकते हैं कि आप सभी पंक्तियों, या इसे करने का सबसे अच्छा तरीका है।

ध्यान दें कि क्वेरी में LIMIT होने से आपको कुल संख्या क्वेरी LIMIT के बिना वापस आ जाएगी।

0

जैसा कि पहले से ही कहा गया है, आपको वास्तव में पंक्तियों को खोजने की आवश्यकता है कि क्या कोई है या नहीं। यदि आपको प्रत्येक पंक्ति पर लूप शुरू करने से पहले पता होना चाहिए, और यदि अपेक्षित परिणाम विशाल नहीं हैं, तो आप सभी परिणामों को सरणी में प्राप्त कर सकते हैं, और फिर उसे जांच सकते हैं।

मैं हाल ही में ऐसा ही कुछ प्रयोग किया है:

foreach my $table (qw(ACTOR DIRECTOR PRODUCER WRITER)) { 
    my $sth = $dbi->prepare(qq{SELECT * FROM $table WHERE DESCRIPTION != TRIM(DESCRIPTION)}) 
     or die $dbi->errstr; 
    $sth->execute or die $sth->errstr; 

    my @rows = @{ $sth->fetchall_arrayref() }; 

    next unless @rows; 

    foreach my $row (@rows) { 
     print join(", ", map {qq("$_")} @{$row}), "\n"; 
    } 
} 
संबंधित मुद्दे

 संबंधित मुद्दे