2014-09-30 6 views
5

में संबंधित स्थिर क्वेरी के समान चीज़ को वापस नहीं लौटा रही है। मैं हास्केल में SQL क्वेरी जेनरेट कर रहा हूं और उन्हें एचडीबीसी का उपयोग कर SQLite (3) डेटाबेस में सबमिट कर रहा हूं।जेनरेटेड एसक्यूएल क्वेरी एसक्लाइट 3 एचडीबीसी

import Database.HDBC.Sqlite3 
import Database.HDBC 
data UmeQuery = UmeQuery String [SqlValue] deriving Show 

tRunUmeQuery :: UmeQuery -> FilePath -> IO [[SqlValue]] 
tRunUmeQuery (UmeQuery q args) dbFile = do 
    conn <- connectSqlite3 dbFile 
    stat <- prepare conn q 
    s <- execute stat args 
    res <- fetchAllRows' stat 
    disconnect conn 
    return $ res 

selectPos targetlt parentlt op pos = let 
    q= "select TARGET.* from levels tl, labeltypes tlt, segments TARGET, 
    (select TARGET.session_id session_id,SECONDARY.labeltype_id labeltype_id, 
    SECONDARY.label_id label_id,min(TARGET.label_id) min_childlabel_id from 
    levels tl, labeltypes tlt, segments TARGET, segments SECONDARY, labeltypes slt, 
    levels sl where TARGET.session_id = SECONDARY.session_id and ((SECONDARY.start 
    <= TARGET.start and TARGET.end <= SECONDARY.end) or (TARGET.start <= SECONDARY.start 
    and SECONDARY.end <= TARGET.end)) and tl.name = ? and sl.name = ? and SECONDARY.label ' 
    != '' and tl.id = tlt.level_id and sl.id = slt.level_id and tlt.id = TARGET.labeltype_id 
    and slt.id = SECONDARY.labeltype_id group by TARGET.session_id, TARGET.labeltype_id, 
    SECONDARY.label_id) SUMMARY, segments SECONDARY, labeltypes slt, levels sl where 
    TARGET.session_id = SECONDARY.session_id and TARGET.session_id = SUMMARY.session_id 
    and ((SECONDARY.start <= TARGET.start and TARGET.end <= SECONDARY.end) or (TARGET.start 
    <= SECONDARY.start and SECONDARY.end <= TARGET.end)) and tl.name = ? and sl.name = ? 
    and tl.id = tlt.level_id and tlt.id = TARGET.labeltype_id and SUMMARY.labeltype_id = 
    SECONDARY.labeltype_id and SUMMARY.label_id = SECONDARY.label_id and sl.id = slt.level_id 
    and slt.id = SECONDARY.labeltype_id and (TARGET.label_id - SUMMARY.min_childlabel_id +1) = 2 " 
    a = [toSql targetlt, toSql parentlt, toSql targetlt, toSql parentlt ] 
    in UmeQuery q a 

, जो जब डेटाबेस के लिए लागू सही काम देता है:

> let a =selectPos "Word" "Utterance" "=" 2 
> let b = tRunUmeQuery a testdb 
> b 

आउटपुट:

[[SqlByteString "1", SqlByteString अब, यह समारोह एक प्रश्न रिटर्न "2", एसक्लबाइटस्ट्रिंग "3", एसक्लबेटस्ट्रिंग "0.149383838383838", एसक्लबेटस्ट्रिंग "0.312777777777778", एसक्लबेटस्ट्रिंग "दूसरा"], [एसक्लबेटस्ट्रिंग "1", एसक्लबेटस्ट्रिंग "2", एसक्लबीस्टस्ट्रिंग "6", SqlByteString ".507488888888889",, SqlByteString ".655905050505051", SqlByteString "चौथा"] [SqlByteString "2", SqlByteString "2", "3" SqlByteString, ".149383838383838" SqlByteString, SqlByteString ".312777777777778", "दूसरी"] SqlByteString, [ "2" SqlByteString, "2" SqlByteString, "6", SqlByteString ".507488888888889" SqlByteString, SqlByteString ".655905050505051", SqlByteString "चौथा"], [SqlByteString "3", SqlByteString " 2 ", SqlByteString" 3 ", SqlByteString " .149383838383838 ", SqlByteString" .312777777777778 ", SqlByteString" दूसरी "], [SqlByteString" 3 ", SqlByteString" 2 ", SqlByteString " 6 ", SqlByteString" .507488888888889 ",SqlByteString 210 ".655905050505051", SqlByteString "चौथा"]]

अब, जब मैं (क्षमा करें, आप के लिए स्ट्रिंग के अंत तक स्क्रॉल करने के लिए है इस तरह क्वेरी में छोटे गतिशील भागों के एक जोड़े को सम्मिलित करने की जरूरत है, इस देखें):

selectPos targetlt parentlt op pos = let 
    q= "select TARGET.* from levels tl, labeltypes tlt, segments TARGET, 
    (select TARGET.session_id session_id,SECONDARY.labeltype_id labeltype_id, 
    SECONDARY.label_id label_id,min(TARGET.label_id) min_childlabel_id from 
    levels tl, labeltypes tlt, segments TARGET, segments SECONDARY, labeltypes slt, 
    levels sl where TARGET.session_id = SECONDARY.session_id and ((SECONDARY.start 
    <= TARGET.start and TARGET.end <= SECONDARY.end) or (TARGET.start <= SECONDARY.start 
    and SECONDARY.end <= TARGET.end)) and tl.name = ? and sl.name = ? and SECONDARY.label 
    != '' and tl.id = tlt.level_id and sl.id = slt.level_id and tlt.id = TARGET.labeltype_id 
    and slt.id = SECONDARY.labeltype_id group by TARGET.session_id, TARGET.labeltype_id, 
    SECONDARY.label_id) SUMMARY, segments SECONDARY, labeltypes slt, levels sl where 
    TARGET.session_id = SECONDARY.session_id and TARGET.session_id = SUMMARY.session_id 
    and ((SECONDARY.start <= TARGET.start and TARGET.end <= SECONDARY.end) or (TARGET.start 
     <= SECONDARY.start and SECONDARY.end <= TARGET.end)) and tl.name = ? and sl.name = ? 
     and tl.id = tlt.level_id and tlt.id = TARGET.labeltype_id and SUMMARY.labeltype_id = 
     SECONDARY.labeltype_id and SUMMARY.label_id = SECONDARY.label_id and sl.id = slt.level_id 
     and slt.id = SECONDARY.labeltype_id and (TARGET.label_id - SUMMARY.min_childlabel_id +1) " 
     ++ op ++ " ? " 
    a = [toSql targetlt, toSql parentlt, toSql targetlt, toSql parentlt , toSql pos] 
    in UmeQuery q a 

और एक ही बात करते हैं, मैं:

> let a =selectPos "Word" "Utterance" "=" 2 
> let b = tRunUmeQuery a testdb 
> b 

[]

दूसरी क्वेरी कैसे वापस आती है (या, वही चीज़ वास्तव में)?

कोई विचार?

संपादित करें:

Ive यह आगे की जांच की, यह सोचकर कि इससे किसी भी तरह आलसी से कोई लेना देना हो सकता है। ठीक है, का अब यह करने के लिए नया रूप दिया गया है

selectPos :: String -> String -> String -> Integer -> [[SqlValue]] 
selectPos targetlt parentlt op pos = let 
    q= foldl' (++) [] ["select TARGET.* from levels tl, labeltypes tlt, segments TARGET, 
    (select TARGET.session_id session_id,SECONDARY.labeltype_id labeltype_id,SECONDARY.label_id 
    label_id,min(TARGET.label_id) min_childlabel_id from levels tl, labeltypes tlt, segments 
    TARGET, segments SECONDARY, labeltypes slt, levels sl where TARGET.session_id = SECONDARY.session_id " 
    ,matchstring , " and tl.name = ? and sl.name = ? and SECONDARY.label != '' and tl.id = tlt.level_id 
    and sl.id = slt.level_id and tlt.id = TARGET.labeltype_id and slt.id = SECONDARY.labeltype_id 
    group by TARGET.session_id, TARGET.labeltype_id, SECONDARY.label_id) SUMMARY, segments SECONDARY, 
    labeltypes slt, levels sl where TARGET.session_id = SECONDARY.session_id and TARGET.session_id = 
    SUMMARY.session_id " , matchstring , " and tl.name = ? and sl.name = ? and tl.id = tlt.level_id 
    and tlt.id = TARGET.labeltype_id and SUMMARY.labeltype_id = SECONDARY.labeltype_id and SUMMARY.label_id 
    = SECONDARY.label_id and sl.id = slt.level_id and slt.id = SECONDARY.labeltype_id and 
    (TARGET.label_id - SUMMARY.min_childlabel_id +1) " , op , " ? "] 
    a = [toSql targetlt, toSql parentlt, toSql targetlt, toSql parentlt , toSql (pos :: Integer)] 
    in UmeQuery q a 

दुर्भाग्य से, इस मुद्दे को मदद नहीं करता है (और जब मैं: GHCi में समारोह की वापसी मान स्प्रिंट, यह अभी भी में unevaluated)। तो, आलस्य किसी भी तरह का मुद्दा हो सकता है, लेकिन मुझे नहीं पता कि यह पूरी तरह से मूल्यांकन कैसे किया जाए ..? कृपया, कोई विचार?

+0

आप न्यूलाइन का उपयोग करना चाहेंगे ताकि SQL कमांड पठनीय हो सके। जेनरेट एसक्यूएल भी दिखाएं। –

+0

हो गया! कृपया मुझे समझने में सहायता करें कि इन दो प्रश्नों को उसी तरह क्यों निष्पादित नहीं किया गया है। –

+0

मेरे उत्तर पर नज़र डालें और मुझे बताएं कि क्या मैं कुछ सेट अप करता हूं जो कि आप जो चल रहे हैं उससे काफी अलग है। मैं ईमानदारी से किसी और चीज के बारे में सोच नहीं सकता। मैं उन तारों को संयोजित करके एक खाली सेट को पुन: पेश नहीं कर सकता (जो अनिवार्य रूप से आप बदलते हैं)। –

उत्तर

3

तो ...सिर्फ तथ्यों को बताने के लिए:

  • अपने कोड चलती है यह किसी भी वाक्यविन्यास त्रुटियों या चेतावनी का उत्पादन नहीं करता (और यह दोनों Haskell और एसक्यूएल कि Haskell से भाग गया है के लिए है)
  • मूल प्रश्न लेकिन सेशन और कहा कि स्थिति के साथ नहीं चलती है
  • आप एक खाली सेट वापस मिल (अर्थ, क्वेरी कोई भी पंक्ति रिटर्न) (वहाँ यह करने के लिए पहले से ही गतिशील भागों थे) ...

यदि ये सभी चीजें सत्य हैं, तो यह मुझे विश्वास दिलाती है कि क्वेरी वैध लेकिन गलत होना चाहिए। डेटा जांचें? क्वेरी को डंप करें, इसे मैन्युअल रूप से चलाएं। मुझे बताएं।

तुएं:

  • यदि यह अभी भी काम करता है देखने के लिए (ताकि आप जानते हैं कि कुछ भी नहीं गलती से बदल दिया गया और सत्यापित करने के लिए डेटा एक ही है) परिवर्तन वापस किए कोशिश करो।
  • क्या आप एक सरल क्वेरी के साथ परीक्षण करने का प्रयास कर सकते हैं?
  • क्या आप क्वेरी वैरिएबल को डंप करने और डीबी में इसे मैन्युअल रूप से चलाने का प्रयास कर सकते हैं (परिवर्तन के साथ और बिना)?
  • क्या आप अपने डेटा की कुछ पंक्तियां पोस्ट करना चाहते हैं (कुछ पंक्तियां जो वापस आ जाएंगी, कुछ जो नहीं करेंगे) तो मैं इसे इसके साथ एक टेम्पलेट टेबल टेस्ट में लोड कर सकता हूं?
  • काम कर क्वेरी के लिए सिर्फ pos जोड़ने का प्रयास करें (साथ op हार्ड-कोडेड) और है कि अगर काम करता है
  • काम कर क्वेरी के लिए सिर्फ op जोड़ने की कोशिश को देखने के (साथ pos हार्ड-कोडेड) और देखते हैं कि अगर काम करता है
  • मेक सुनिश्चित करें कि आप अपने चर को हर जगह सही क्रम में सूचीबद्ध कर रहे हैं

किसी कारण से, मैं सोचता रहता हूं कि यह कास्टिंग या कुछ के साथ डेटाटाइप मुद्दा हो सकता है लेकिन मैंने कभी हास्केल के साथ काम नहीं किया है, इसलिए मैं वास्तव में नहीं कर सकता अनुमान लगाओ कि और क्या हो रहा है।

अन्य सुझाव:

  • format your query ठीक से तो यह आसानी से पढ़ने योग्य है (कम से कम एक छोटे से, तो यह एक बहुत बड़ा स्ट्रिंग नहीं है)
  • अद्यतन अपने प्रश्न अपने परिवेश के लिए निर्धारित है पर विनिर्देशों शामिल करने के लिए अप (सॉफ्टवेयर/चीजों और सामान के संस्करणों के साथ)
  • यदि आपको लगता है कि समस्या आलसी से जुड़ी है, try forcing evaluation ...? लेकिन क्वेरी में पहले से ही गतिशील/परिवर्तनीय भागों थे। मुझे यह मानना ​​होगा कि अगर यह मामला था, तो उन्हें एक ही समस्या होगी, और क्वेरी शुरू करने के लिए काम नहीं करती थी।
  • यह मूर्खतापूर्ण होगा, लेकिन आप जो डीबी खींच रहे हैं उसे बदलने के लिए आप नहीं हुए थे, है ना?

sqlite> select * from temp; 
temp_id  temp_name 
---------- ---------- 
1   one 
2   two 
3   three 
import Database.HDBC.Sqlite3 
import Database.HDBC 

testdb = "C:\\Users\\Kim!\\test.db" 

data UmeQuery = UmeQuery String [SqlValue] deriving Show 

tRunUmeQuery :: UmeQuery -> FilePath -> IO [[SqlValue]] 

tRunUmeQuery (UmeQuery q args) dbFile = do 
    conn <- connectSqlite3 dbFile 
    stat <- prepare conn q 
    s <- execute stat args 
    res <- fetchAllRows' stat 
    disconnect conn 
    return $ res 

selectPos temp_id op = let 
    q = "select temp_id, temp_name from temp where temp_id " ++ op ++ " ?"; 
    a = [ toSql temp_id ] 
    in UmeQuery q a 
> let a = selectPos (1::Int) "=" 
> let b = tRunUmeQuery a testdb 
> b 
[[SqlByteString "1",SqlByteString "one"]] 

> let a = selectPos (1::Int) ">" 
> let b = tRunUmeQuery a testdb 
> b 
[[SqlByteString "2",SqlByteString "two"],[SqlByteString "3",SqlByteString "three"]] 

त्वरित टिप्पणी: मैं आज से पहले हास्केल या SQLite छुआ नहीं किया है। मैं विंडोज 7 व्यावसायिक 64 बिट पर इस SQLite3 - sqlite-dll-win64-x64-201409301904.zip के साथ हास्केल प्लेटफ़ॉर्म 2014.2.0.0 चला रहा हूं।

संपादित करें: यह भी काम करता है ... (क्वेरी एक लील अलग है, भी)

import Data.List 

selectPos temp_id op temp_name = let 
    q = foldl' (++) [] [ 
     "select temp_id, temp_name  " ++ 
     "from temp      " ++ 
     "where temp_id " , op , " ? or " ++ 
     "  temp_name = ?    "] 
    a = [ toSql (temp_id::Int), toSql temp_name ] 
    in UmeQuery q a 

> let a = selectPos 1 ">" "one" 
> let b = tRunUmeQuery a testdb 
> b 
[[SqlByteString "1",SqlByteString "one"],[SqlByteString "2",SqlByteString "two"],[SqlByteString "3",SqlByteString "three"]] 

संपादित करें: और इस काम करता है ...

sqlite> insert into temp values (4, "Word"); 
sqlite> insert into temp values (5, "Utterance"); 

selectPos targetlt parentlt op pos = let 
    q = " select temp_id, temp_name  \ 
     \ from temp      \ 
     \ where temp_name = ? or   \ 
     \  temp_name = ? or   \ 
     \  temp_name = ? or   \ 
     \  temp_name = ? or   \ 
     \  temp_id "++op++" ?  " 
    a = [toSql targetlt, toSql parentlt, 
     toSql targetlt, toSql parentlt, 
     toSql (pos::Int) ] 
    in UmeQuery q a 

> let a = selectPos "Word" "Utterance" "=" 2 
> let b = tRunUmeQuery a testdb 
> b 
[[SqlByteString "2",SqlByteString "two"],[SqlByteString "4",SqlByteString "Word"],[SqlByteString "5",SqlByteString "Utterance"]] 

तो ... आपके प्रश्नों में आपने प्रश्न में पोस्ट किया है ... एक अप्रत्याशित अंतर भी है ... जो चर के साथ नहीं है। यह एक ही उद्धरण है। सुनिश्चित नहीं है कि कॉपी और पेस्ट या क्या में एक टाइपो है। मैं स्पष्ट रूप से आपकी क्वेरी नहीं चलाया जा सकता, क्योंकि यह वास्तव में है, क्योंकि है कि नकली तालिकाओं और डेटा की एक बड़ी मात्रा साथ आने के लिए है ...

enter image description here

संपादित करें: हां ... मैं वापस इस के लिए फिर से आया था । मैंने देखा है कि आपके पिछले selectPos उदाहरण से ऊपर एक अतिरिक्त पंक्ति थी जिसका मैं उपयोग नहीं कर रहा था। मुझे इसे काम करने के लिए ऐसा करना था ... [[SqlValue]] या IO [[SqlValue]] क्योंकि आखिरी मूल्य मेरे लिए काम नहीं करता था; त्रुटियां (मैं बस चीजों की कोशिश कर रहा हूं, मुझे नहीं पता कि इनमें से कोई भी मूल्य वास्तव में समझ में आता है)।

selectPos :: String -> String -> String -> Integer -> UmeQuery 
selectPos targetlt parentlt op pos = let 
    q = " select temp_id, temp_name  \ 
     \ from temp      \ 
     \ where temp_name = ? or   \ 
     \  temp_name = ? or   \ 
     \  temp_name = ? or   \ 
     \  temp_name != ? or  \ 
     \  temp_id "++op++" ?  " 
    a = [toSql targetlt, toSql parentlt, 
     toSql targetlt, toSql parentlt, 
     toSql pos ] 
    in UmeQuery q a 

> let a = selectPos "Word" "Utterance" "=" 2 
> let b = tRunUmeQuery a testdb 
> b 
[[SqlByteString "1",SqlByteString "one"],[SqlByteString "2",SqlByteString "two"],[SqlByteString "3",SqlByteString "three"],[SqlByteString "4",SqlByteString "Word"],[SqlByteString "5",SqlByteString "Utterance"]] 

इस पर कोई रास्ता ... मुझे खुशी है कि मुझे आज अपना पहला हास्केल प्रोग्राम लिखना है ...!

+0

आपके प्रयास के लिए धन्यवाद। मुझे यकीन नहीं है कि दूसरे एसक्यूएल कथन में अतिरिक्त ''char' डाला गया है, लेकिन मुझे नहीं लगता कि यह ऐसा है। मुझे 'sqlInt64 2' वापस 'toSql' से मिलता है। क्या यह समस्या हो सकती है..? –

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