简体   繁体   English

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

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

I'm testing a database where i have 3 tables, number 1 is storing user information, number 2 is storing the latitude and longitude for different cities, and there's a 3rd table storing the location of a user and it's distance to the closest city. 我正在测试一个数据库,其中有3个表,第1个表存储用户信息,第2个表存储不同城市的纬度和经度,还有第三个表存储用户的位置及其到最近城市的距离。 The 3rd table has a composite key from primary keys of the other two tables. 第三个表具有来自其他两个表的主键的组合键。 I have written a stored procedure in mysql workbench that takes in 5 variables then it inserts data into the 3rd table, here's the code using some random variables: 我已经在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);

it works just fine and inserts into the table, but when i try to call the same procedure with the same variables from python, it does nothing: 它工作正常,并插入到表中,但是当我尝试从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))

It is And when i use 当我使用

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

it gives another Error saying "Unknown column 'Gilan' in 'field list'". 它给出了另一个错误,指出“字段列表中的未知列'Gilan'”。 The interesting part is that if i insert the same data into the table manually, then when i try to call the procedure from python, it raises the error : "Duplicate entry '70440675-883' for key 'PRIMARY'". 有趣的是,如果我手动将相同的数据插入表中,那么当我尝试从python调用该过程时,它会引发错误:“键'PRIMARY'的条目'70440675-883'重复”。 so it seems like it tries to insert into the table, but it doesn't save it !! 因此,似乎它试图插入到表中,但是并没有保存它! Can somebody please tell me what am i doing wrong here?? 有人可以告诉我我在做什么错吗?

My guess is that perhaps there are some rounding issues between the 2nd and 3rd queries of the stored procedure. 我的猜测是,存储过程的第二和第三查询之间可能存在一些舍入问题。 You might consider eliminating the 2nd query altogether, and just change the 3rd query to something like this: 您可能会考虑完全消除第二个查询,而只是将第三个查询更改为以下内容:

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

*I say "something like" because I primarily work in MSSQL lately, and didn't do a lot of SELECT INTO when I was in MySQL more often. *之所以说“类似”,是因为我最近主要在MSSQL中工作,而在我更频繁地使用MySQL时,并没有做很多SELECT INTO操作。 (Specifically, I don't recall if you can alias and into like this.) (具体来说,我不记得您是否可以使用别名和类似的名称。)

Answer ----->> so finally i was able to make it work, the trick was to add mydb.commit() after i call the procedure from python 回答----- >>,所以最终我能够使它工作,诀窍是在我从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))

it's not mentioned in the documentation that we need to use .commit() after using .callproc() method, especially when all the updating and inserting is being done on the database side. 在文档中没有提到在使用.callproc()方法之后我们需要使用.commit() ,特别是当所有更新和插入都在数据库端完成时。 But, it is mentioned in .commit() documentation that 但是, .commit()文档中提到

Since by default Connector/Python does not autocommit, it is important to call this method after every transaction that modifies data for tables that use transactional storage engines. 由于默认情况下Connector / Python不会自动提交,因此在每次修改使用事务存储引擎的表的数据的事务之后,调用此方法很重要。

So my guess is since the procedure tries to manipulate data on the database and it's called from the python client, we need to use .commit() after using .callproc(). 所以我的猜测是,由于该过程试图处理数据库上的数据,并且是从python客户端调用的,因此在使用.callproc()之后,我们需要使用.commit()。

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

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