2016-07-21 8 views
0

あるテーブルの行をループして別のテーブルに挿入する単純なストアドプロシージャを作成しました。なんらかの理由でEND WHILEループでセミコロンエラーが発生しています。すべてのコードは私にとっては右に見え、すべての区切り文字は正しく設定されていました。私はちょうどそれがなぜこれらのエラーを投げているのか分かりません、この問題を尋ねるだけでは、間違ってデリミタの答えを使用して私を指摘しましたが、それ以上はありません。どんな助けもいいだろう!終了whileループがセミコロンでない

:私は、コードの大きなブロックで問題に立ち往生していますし、問題がどこにあるか、私は通常、小さな塊に私のコードを分割し、一度に一つにそれらをテスト見つけることができません

USE test; 
DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
DECLARE i INT DEFAULT 0; 
SELECT COUNT(*) FROM `test_dropship_upload` INTO n; 
SET i=0; 
WHILE i<n DO 
    INSERT INTO `test_2` (sku, qty) VALUES(sku, qty) FROM `test_dropship_upload` LIMIT i,1; 
    SET i = i + 1; 
END WHILE; 

END $$ 

DELIMITER ; 

答えて

1

試験1:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE testLoop() 
BEGIN 
END $$ 

DELIMITER ; 

エラーなし:プロシージャ宣言とデリミタの使用はOKです。

試験2:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
DECLARE i INT DEFAULT 0; 
END $$ 

DELIMITER ; 

エラーなし:手順内の変数の宣言はOKです。

テスト3:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
DECLARE i INT DEFAULT 0; 
SELECT COUNT(*) FROM `test_dropship_upload` INTO n; 
SET i=0; 
END $$ 

DELIMITER ; 

エラーなし:SELECTクエリと変数の割り当てはOKです。

試験4:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
DECLARE i INT DEFAULT 0; 
SELECT COUNT(*) FROM `test_dropship_upload` INTO n; 
SET i=0; 
WHILE i<n DO 
    SET i = i + 1; 
END WHILE; 

END $$ 

DELIMITER ; 

エラーなし:WHILEループはOKです。

試験5:

のみテストされていない部分は今INSERTクエリです:

INSERT INTO `test_2` (sku, qty) VALUES(sku, qty) FROM `test_dropship_upload` LIMIT i,1; 

INSERTINSERT ... SELECTのドキュメントを見ると、私たちはあなたのクエリが有効でないことがわかります。それ他のテーブルから値を挿入したい場合は、の部分が表示されています。

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
DECLARE i INT DEFAULT 0; 
SELECT COUNT(*) FROM `test_dropship_upload` INTO n; 
SET i=0; 
WHILE i<n DO 
    INSERT INTO `test_2` (sku, qty) SELECT sku, qty FROM `test_dropship_upload` LIMIT i, 1; 
    SET i = i + 1; 
END WHILE; 

END $$ 

DELIMITER ; 

プロシージャの作成がエラーなく完了しました。

試験6:手順を実行する際に

ただし、SELECTクエリの構文エラーを取得します:MySQLは変数でLIMITを使用して受け付けません。
動作させるには、prepared statementを使用する必要があります。

PREPARE stmt FROM "INSERT INTO `test_2` (sku, qty) SELECT sku, qty FROM `test_dropship_upload` LIMIT ?, 1"; 
EXECUTE stmt using @i; 
DEALLOCATE PREPARE stmt; 

It is also not allowed to used local variables in prepared statements

ローカル変数のみが格納されたプログラム 実行時にスコープ内にあるため、それらへの参照が格納されたプログラム内で作成されたプリペアドステートメント では許可されていません。準備されたステートメントスコープは、ストアされたプログラムではなく、 現在のセッションです。ステートメントは、プログラムが終了した後に実行される になります。その時点で、変数は より長くなります。たとえば、SELECT ... INTO local_varは、 をプリペアドステートメントとして使用できません。この制限は、格納された プロシージャとファンクションのパラメータにも適用されます。

代わりに、ローカル変数iのセッション変数@iを使用して、この問題を回避するには、次の

手順の最終バージョン:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
SELECT COUNT(*) FROM `test_dropship_upload` INTO n; 
SET @i=0; 
WHILE @i<n DO 
    PREPARE stmt FROM "INSERT INTO `test_2`(sku, qty) SELECT sku, qty FROM `test_dropship_upload` LIMIT ?, 1"; 
    EXECUTE stmt USING @i; 
    DEALLOCATE PREPARE stmt; 
    SET @i = @i + 1; 
END WHILE; 

END $$ 

DELIMITER ; 

あなたはデバッグに同じ方法を適用することができます多くの複雑なプログラミングの問題:単純なバージョンのコードから始め、テストします。より多くのコードを使ってテストを再実行する場合は、エラーを見つけて修正してから続行してください。

+0

完全に見て、助けてくれてありがとう、すべてがいい –

関連する問題