繁体   English   中英

存储过程可在MySQL工作台上使用,但不适用于python

[英]Stored procedure works on MySQL workbench, but not in python

我正在测试一个数据库,其中有3个表,第1个表存储用户信息,第2个表存储不同城市的纬度和经度,还有第三个表存储用户的位置及其到最近城市的距离。 第三个表具有来自其他两个表的主键的组合键。 我已经在mysql工作台中编写了一个存储过程,该存储过程接受5个变量,然后将数据插入到第3个表中,这是使用一些随机变量的代码:

SET @lat55 = 36.8451995849609;
SET @lng55 = 54.428798675537;
SET @city55 = 'Rasht';
SET @state55 = 'Gilan';
SET @user_id55 = 70440675;


DELIMITER //  
DROP PROCEDURE IF EXISTS do1 //
CREATE PROCEDURE do1 (IN id INT, IN state VARCHAR(25), IN city VARCHAR(25),             
IN lat DECIMAL(15,13),IN lng DECIMAL(15,12))
BEGIN

`  `DECLARE dmini DECIMAL(5,1);
    DECLARE lmini INT;

    SELECT location_id, ST_Distance_Sphere(POINT(lng,lat), geopoint)/1000 AS 
    distance INTO lmini, dmini FROM locations ORDER BY distance ASC LIMIT 1;

    INSERT INTO user_has_loc (user_id, location_id, distance, state, city, 
    lat, lng) VALUES (id, lmini, dmini, state, city, lat, lng);
END;
//

CALL do1(@user_id55,@state55,@city55,@lat55,@lng55);

它工作正常,并插入到表中,但是当我尝试从python使用相同的变量调用相同的过程时,它什么也不做:

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="root",
        password="123456",
        database="v21")
    c = mydb.cursor()

    lat = 36.8451995849609
    lng = 54.428798675537
    city = "Rasht"
    state = "Gilan"
    user = 70440675

    arg = (user, state, city, lat, lng)

    c.callproc('do1', arg)

except mysql.connector.Error as err:
    print("Something went wrong: {}".format(err))

当我使用

c.execute("CALL do1({},{},{},{},{})".format(user, state, city, lat, lng))

它给出了另一个错误,指出“字段列表中的未知列'Gilan'”。 有趣的是,如果我手动将相同的数据插入表中,那么当我尝试从python调用该过程时,它会引发错误:“键'PRIMARY'的条目'70440675-883'重复”。 因此,似乎它试图插入到表中,但是并没有保存它! 有人可以告诉我我在做什么错吗?

我的猜测是,存储过程的第二和第三查询之间可能存在一些舍入问题。 您可能会考虑完全消除第二个查询,而只是将第三个查询更改为以下内容:

SELECT location_id, ST_Distance_Sphere(@pt1, geopoint)/1000 AS distance
INTO @lmini, @mini
FROM locations
ORDER BY distance ASC
LIMIT 1;

*之所以说“类似”,是因为我最近主要在MSSQL中工作,而在我更频繁地使用MySQL时,并没有做很多SELECT INTO操作。 (具体来说,我不记得您是否可以使用别名和类似的名称。)

回答----- >>,所以最终我能够使它工作,诀窍是在我从python调用过程之后添加mydb.commit()

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="root",
        password="123456",
        database="v21")
    c = mydb.cursor()

    lat = 36.8451995849609
    lng = 54.428798675537
    city = "Rasht"
    state = "Gilan"
    user = 70440675

    arg = (user, state, city, lat, lng)

    c.callproc('do1', arg)
    mydb.commit()

except mysql.connector.Error as err:
    print("Something went wrong: {}".format(err))

在文档中没有提到在使用.callproc()方法之后我们需要使用.commit() ,特别是当所有更新和插入都在数据库端完成时。 但是, .commit()文档中提到

由于默认情况下Connector / Python不会自动提交,因此在每次修改使用事务存储引擎的表的数据的事务之后,调用此方法很重要。

所以我的猜测是,由于该过程试图处理数据库上的数据,并且是从python客户端调用的,因此在使用.callproc()之后,我们需要使用.commit()。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM