2017-09-01 7 views
0

Ich arbeite an einer Prozedur, die meine Artikel verkauft. Wenn ich versuche, es anzurufen, sagt es mir diese Fehlermeldung. Ich überprüfte, welcher Teil mehr Zeilen zurückgibt, aber ich konnte es nicht herausfinden. Hier ist der Code für dieses Verfahren:Fehler 1242: Unterabfrage gibt mehr als 1 Zeile zurück - warum?

DELIMITER // 
CREATE PROCEDURE SellItem(pCharacterName varchar(50), pItemName varchar(50), howManyItems int(11)) 
BEGIN 

DECLARE pchar int(11); 
DECLARE pitem int(11); 
DECLARE pitemCost int(11); 
DECLARE pcharMoney int(11); 
DECLARE newMoneyValue int(11); 
DECLARE cnt int(11) DEFAULT 1; 
DECLARE pcharitid int(11); 

SET pchar=(SELECT `getChar`(`pCharacterName`)); 
SET pitem=(SELECT `getItem`(`pItemName`)); 
SET pitemCost=(SELECT `price` FROM `item` WHERE `item`.`item_id`=pitem); 
SET pcharMoney=(SELECT `money` FROM `character` WHERE `character`.`character_id`=pchar); 
SET newMoneyValue=pcharMoney; 
WHILE cnt<=`howManyItems` DO 
SET newMoneyValue=newMoneyValue+pitemCost; 
SET cnt=cnt+1; 
END WHILE; 
SET cnt=1; 

WHILE cnt<=`howManyItems` DO 
SET pcharitid=(SELECT MAX(`character_item_id`) FROM `character_item` WHERE `character_item`.`character_id`=pchar AND `character_item`.`item_id`=pitem); 
IF (SELECT `item_id` FROM `character_item` WHERE `character_item`.`item_id` IN(SELECT `item_id` FROM `item` WHERE `item`.`name`=`pItemName`)) THEN 
DELETE FROM `character_item` WHERE `character_item`.`character_item_id`=pcharitid; 
UPDATE `character` SET `money`=newMoneyValue WHERE `character`.`character_id`=pchar; 
SET cnt=cnt+1; 
END IF; 
END WHILE; 
END; // 
DELIMITER ; 

Die Funktionen Ich nenne sind einfache Funktionen, die mir die ID des ausgewählten Zeichens/Stück zurückzukehren.

+0

Die Fehlermeldung konnte nicht klarer sein. Ihre Auswahl gibt mehr als eine Zeile zurück. – Eric

+0

Danke für das, was ich schon wusste. – Daelendil

+0

Wenn Sie bereits wissen, was nicht stimmt, führen Sie die individuelle SELECT-Anweisung aus, um herauszufinden, welche Ihnen mehr als 1 Zeile geben. – Eric

Antwort

1

Wenn Sie ein SELECT in einem Kontext aufrufen, der nur einen Wert erfordert, aber das SELECT nicht logisch garantiert nur einen Wert zurückgibt, dann erhalten Sie diesen Fehler.

Sie haben sechs SELECT-Operationen:

SET pchar=(SELECT `getChar`(`pCharacterName`)); 
SET pitem=(SELECT `getItem`(`pItemName`)); 

Diese beiden sind eine gespeicherte Funktion auf einem skalaren Parameter aufrufen. Sie sind in Ordnung, denn in beiden Fällen kann nur ein Wert zurückgegeben werden.

SET pitemCost=(SELECT `price` FROM `item` WHERE `item`.`item_id`=pitem); 

Diese SELECT ist wahrscheinlich in Ordnung. Ich gehe davon aus, item.item_id ist der Primärschlüssel dieser Tabelle, so dass es nur eine Zeile (oder null Zeilen) übereinstimmen kann.

SET pcharMoney=(SELECT `money` FROM `character` WHERE `character`.`character_id`=pchar); 

Ebenso scheint dies in Ordnung, vorausgesetzt, character.character_id ein Primärschlüssel ist.

SET pcharitid=(SELECT MAX(`character_item_id`) FROM `character_item` WHERE `character_item`.`character_id`=pchar AND `character_item`.`item_id`=pitem); 

Dies ist sicher nur einen Wert zurückgeben, weil Sie keine GROUP BYMAX() und die Abfrage hat verwenden.

IF (SELECT `item_id` FROM `character_item` WHERE `character_item`.`item_id` IN 
    (SELECT `item_id` FROM `item` WHERE `item`.`name`=`pItemName`)) THEN 

Die innere Unterabfrage muss nicht ein Skalar sein, weil sie Teil eines IN() Prädikat ist, die gegen mehrere Werte vergleichen können.

Die äußere Abfrage muss eine skalare Abfrage sein, ist es aber nicht. Je nach Ihren Daten können mehrere Zeilen zugeordnet werden, sodass sie in einer IF()-Bedingung nicht logisch verwendet werden können.

Sie können es entweder meine mit SELECT MAX(item_id)... oder mit ...LIMIT 1 am Ende der Abfrage beheben.

+0

Danke, dass Sie mir bei meinem Problem geholfen haben. Ich habe die Klausel LIMIT 1 hinzugefügt und es hat mein Problem behoben. – Daelendil

0

Sie müssen jede Funktion einzeln mit den Testdaten ausführen, die Sie verwenden, um festzustellen, welche mehr als eine Zeile zurückgibt.

z. Führen Sie zuerst dieses:

SELECT 'getChar' ('pCharacterName') 

Aber offensichtlich ersetzt pCharacterName mit Ihren Testdaten.

Verwandte Themen