хранимая процедура mysql с проблемой параметров - PullRequest
1 голос
/ 26 октября 2009

Я создал следующую процедуру.

DELIMITER ;;

DROP PROCEDURE IF EXISTS getAllPortfoliosDemo;;

CREATE PROCEDURE getAllPortfoliosDemo( IN keyid INT(10)) 
    BEGIN 
        DECLARE whereString char(100);

        IF (keyid > 0 ) THEN
            SET  whereString =  CONCAT( ' WHERE pkid = ', keyid );
        ELSE
            SET whereString = ' WHERE 1 ';
        END IF;


        SELECT pkid, title FROM Portfolio whereString;

    END ;;

этот запрос не возвращает ошибок. хорошо работает без параметров. например, CALL getAllPortfoliosDemo (); работает. но это не работает с параметром. например CALL getAllPortfoliosDemo (5); не возвращает ни одной строки.

также я попробовал следующий альтернативный запрос

DELIMITER ;;

DROP PROCEDURE IF EXISTS getAllPortfoliosDemo;;

CREATE PROCEDURE getAllPortfoliosDemo( IN keyid INT(10)) 
    BEGIN 
        DECLARE whereString char(100) DEFAULT NULL;

        IF (keyid > 0 ) THEN
            SET  whereString =  CONCAT( ' AND pkid = ', keyid );
        END IF;


        SET @SQLstmt =  CONCAT('SELECT pkid, title FROM Portfolio ', whereString) ;

        PREPARE SQLbase FROM @SQLstmt;
    EXECUTE SQLbase;
    DEALLOCATE PREPARE SQLbase;

    END ;;       

это также не возвращает никакого набора результатов. любой может самый мудрый метод. заранее спасибо

Ответы [ 2 ]

1 голос
/ 26 октября 2009
SELECT pkid, title 
FROM Portfolio whereString;

Таким образом, ваша переменная whereString преобразуется в BOOLEAN и всегда принимает значение true, поскольку она не пустая.

IF (keyid > 0 ) THEN
    SET  whereString =  CONCAT( ' AND pkid = ', keyid );
END IF;

SET @SQLstmt =  CONCAT('SELECT pkid, title FROM Portfolio ', whereString)

Это должно произойти сбой для значений выше 0, так как это приводит к следующему утверждению:

SELECT  pkid, title
FROM    Portfolio
WHERE   AND pkid = $keyid
--      ^
--  Wrong!

Просто используйте следующее утверждение:

SELECT  pkid, title
FROM    Portfolio
WHERE   pkid = keyid
UNION ALL
SELECT  pkid, title
FROM    Portfolio
WHERE   keyid = 0

Это оптимизирует один из SELECT запросов и будет достаточно эффективным.

0 голосов
/ 27 октября 2009

Да. Quassnoi хорошо ответил на этот вопрос. спасибо ему большое. Я изменил запрос как

DELIMITER ;;

DROP PROCEDURE IF EXISTS getAllPortfoliosDemo;;

CREATE PROCEDURE getAllPortfolios( IN keyid INT(10)) 
    BEGIN 
        DECLARE whereString char(100) DEFAULT NULL;

        IF (keyid > 0 ) THEN
            SET  whereString =  CONCAT( ' WHERE 1 AND pkid = ', keyid );
        ELSE
            SET  whereString =  ' WHERE 1 ';
        END IF;


        SET @SQLstmt =  CONCAT('SELECT pkid, title  FROM Portfolio ', whereString) ;

        PREPARE SQLbase FROM @SQLstmt;
 EXECUTE SQLbase;
 DEALLOCATE PREPARE SQLbase;

    END ;;   

, чтобы CALL getAllPortfoliosDemo (0) возвращал все записи, а CALL getAllPortfoliosDemo (5) возвращает пятую строку

запрос

  CREATE PROCEDURE getAllPortfoliosDemo( IN keyid INT(10)) 
    BEGIN 
       SELECT  pkid, title
       FROM    Portfolio
       WHERE   pkid = keyid
   UNION ALL
      SELECT  pkid, title
      FROM    Portfolio
      WHERE   pkid = 0;
    END ;;

слишком полезно. но «CALL getAllPortfoliosDemo (0)» здесь не повторяет запись, потому что у нас не было записи с идентификатором первичного ключа «0». getAllPortfoliosDemo (5) работает нормально

...