Hej,
Idag fick jag ett mail där en användare berättade om ett MySQL-felmeddelande som förekommit på en sida som jag driver.
Felmeddelandet:
Warning: mysql_query() [function.mysql-query]: Unable to save result set in xxx/threadreply.php on line xxx
Subquery returns more than 1 row
Jag har själv inte sett det här felmeddelandet tidigare. Det dök upp som en blixt från klarblå himmel för mig. Jag förstår vad som står men jag har ännu inte påbörjat felsökning av felet. Tänkte kolla här om det är någon som kan "hinta" mig om varför det här dök upp?
Precis som det står så returnerar en subfråga mer än ett resultat. T.ex. om du har en fråga liknande den här:
SELECT a.user_id,
(SELECT name FROM tabell where id = a.user_id) AS namn
FROM en_annan_tabell
Felet uppstår när subfrågan, den mellan ( och ) ger te.x. två träffar. Enklaste lösningen är att ange LIMIT 1 så fixar det sig.
Alltså:
SELECT a.user_id,
(SELECT name FROM tabell where id = a.user_id LIMIT 1) AS namn
FROM en_annan_tabell
Nu har jag kollat upp vad hänvisningen i felmeddelandet pekar på. Rad 112 är det som verkar utlösa felet. Här är koden:
$RSobj_notify = mysql_query("SELECT COUNT(t1.threadreplyID) AS replynumber FROM tblforumthreadreply AS t1 WHERE t1.threadID = ".$threaddata['threadID']." AND t1.posted > (SELECT t2.date_time FROM tblforumthreadreplynotifier AS t2 WHERE t2.threadID = ".$threaddata['threadID']." AND memberID <> ".$_SESSION["uid"].")") or die (mysql_error());
$notify = mysql_fetch_array($RSobj_notify);
Användarna säger att det här dyker upp sporadiskt? Är det något som man på direkten kan se är fel i koden utan att förstå mer ingående vad den gör?
Peter SMedlem sedan dec. 20025 483 inlägg Som Micke säger så är problemet att
SELECT t2.date_time FROM tblforumthreadreplynotifier AS t2 WHERE t2.threadID = ".$threaddata['threadID']." AND memberID <> ".$_SESSION["uid"]."
...returnerar fler än en rad.
För att åtgärda det föreslår jag att du använder MAX(t2.date_time) i stället.
Testa det här:
SELECT COUNT(t1.threadreplyID) AS replynumber
FROM tblforumthreadreply AS t1
WHERE t1.threadID = <threadID>
AND t1.posted >
(SELECT t2.date_time
FROM tblforumthreadreplynotifier AS t2
WHERE t2.threadID = <threadID>
AND memberID <> <uid>
LIMIT 1
)
Subfrågan får alltså _aldrig_ ge mer än en post som resultat, vilket förhindras men LIMIT 1 som jag lade till ovan.
Tack för snabb respons! Jag ska testa och se vad kodförändringen får för effekt.
Den här funktionen som koden ovan hänger ihop med ser till att medlemmar blir informerade om nya inlägg i en viss tråd om det är så att de valt att prenumera på den. Tabellstrukturen tblforumthreadreplynotifier ser ut som enligt bilden nedan. Primärnyckeln för tabellen är memberID och threadID. Försöker förstår varför det här felet har uppstått nu och inte förekommit tidigare.
*En stund senare*
Nu tror jag att jag har hittat boven i dramat. Det finns två personer i tabellen ovan som båda har valt att prenumera på information om när nytt inlägg postas i aktuell tråd. Därav så returneras två svar när sub-queryn ställs. Det här var absolut inget jag tänkte kunde inträffa när jag skrev koden för länge sen.
Det är just tråden med threadID 1379 som du uttryckt att de har haft problem med och båda dessa medlemmar har prenumererat på tråden i fråga.
Vad tror ni? Verkar det rimligt? Nu försöker jag förstår om LIMIT 1 kan få någon annan konstigt effekt för de som har valt att prenumerera på den här informationen.
Det känns som om du sparar onödigt mycket information och använder den på fel sätt, det blir snarare rörigt.
Tabellen som t.ex. heter "subscribers", där behöver du bara spara user, read_datetime, thread.
När ett nytt inlägg postas kör du en INNER JOIN mellan subscribers och users, där du hämtar alla epostadresser från users, där thread matchar tråden och där read_datetime är tidigare än nu.
Du behöver nog förresten en flagga där, som sätts till "true" när användare faktiskt besöker tråden, för att säkerställa att man bara får en påminnelse och inte en för varje nytt svar, fram tills en nästa besök.
Den här koden skrev jag för 4 år sedan då jag höll på att lära mig programering. Av den anledningen är koden inte helt optimerad i alla avseenden. Nu har jag tagti fram migreringsscript för en övergång till vBulletin. Men jag är med på vad du säger om den aktuella koden.
Spelar ingen roll om koden är gjord igår eller för 10 år sen, men ville bara påpeka det. Du har ju ett problem som vi försöker lösa.
Om du ändå ska migrera så kanske du inte behöver göra något åt det.
Har du provat att lägga in LIMIT 1 i subfrågan?
MickeA: Så här tänker jag kring din kod. Som det är nu är det inte definierat vilken rad som hämtas ut, om det finns flera. Alltså borde man lägga till något i stil med ORDER BY t2.date_time DESC för att få ut det senaste datumet, om det nu är det man vill. Men då kan dock lika gärna använda MAX(t2.date_time) och få:
SELECT COUNT(t1.threadreplyID) AS replynumber
FROM tblforumthreadreply AS t1
WHERE t1.threadID = <threadID>
AND t1.posted >
(SELECT MAX(t2.date_time)
FROM tblforumthreadreplynotifier AS t2
WHERE t2.threadID = <threadID>
AND memberID <> <uid>
)
Jo, visst kan man göra så istället, är förmodligen bättre att använda max.