在mysql存储过程中设置并选择无法正常工作

时间:2016-01-12 18:24:52

标签: mysql sql

我有一个MySQl存储过程,它的行为异常并输出错误。

CREATE PROCEDURE GetVotes(IN postId INT)
BEGIN

DECLARE upVotes INT DEFAULT 0;
DECLARE downVotes INT DEFAULT 0;
DECLARE stars INT DEFAULT 0;

SET upVotes := ( SELECT count(upvote) FROM threadvote WHERE upvote = 1 AND postid = postId );

SET downVotes := (SELECT count(downvote) FROM threadvote WHERE downvote = 1 AND postid = postId );

SET stars := (SELECT count(starred) FROM threadvote WHERE starred = 1 AND postid = postId );

SELECT upVotes as numupvotes, downVotes as numdownvotes , stars as numstars;

END

它像蛋糕一样简单,但它会耗费我的时间,因为它会产生错误的输出。 SET语句设置包含表中所有行数的变量(即它似乎忽略了where子句)。

示例数据:

itemid userid   postid upvote   downvote starred
9      15       9        1        0        0
12     16       9        1        0        1
13     15       7        1        0        0
14     15       8        1        0        1
15     16       7        1        0        1
16     16       8        0        1        0
17     16       11       0        1        0
18     15       11       0        1        0

现在CALL GetVotes(8);给了我:

numupvotes numdownvotes numstars
5          3            2

应该是:

numupvotes numdownvotes numstars
1          1            1

此外,带有@符号的DECLARE会出现语法错误。例如

DECLARE @upVotes INT DEFAULT 0;

给出语法错误。

请告诉我这里有什么问题。 或者我错过了一些mysql服务器设置?

3 个答案:

答案 0 :(得分:2)

您的姓名存在碰撞问题。也就是说,postid = postid几乎总是如此。使用前缀来区分参数:

CREATE PROCEDURE GetVotes(IN in_postId INT)
BEGIN

    DECLARE upVotes INT DEFAULT 0;
    DECLARE downVotes INT DEFAULT 0;
    DECLARE stars INT DEFAULT 0;

    SELECT up_Votes := SUM(upvote = 1), downvote := SUM(downvote = 1),
           stars := SUM(starred = 1)
    FROM threadvote tv
    WHERE tv.postid = in_postId;

    SELECT upVotes as numupvotes, downVotes as numdownvotes , stars as numstars;

END

答案 1 :(得分:0)

你甚至不需要变量,试试这个:

public interface IPort
{
    object SomeAction(object data);
}

public class Port<T> : IPort
{
    //[.. all other methods ..]


    object IPort.SomeAction(object data)
    {
        var typedData = (T)data;
        //invoke our typed version.
        return SomeAction(data);
    }

    public T SomeAction(T data)
    {
         // ...
    }
}

另外,为避免命名冲突,您最好通过在表名前面(或通过表别名)指向表列名称

答案 2 :(得分:0)

将输入参数设置为其他名称 - 例如in_postid。很明显,AND postid = postId只是评估为真正的