Stored procedure works on MySQL workbench, but not in python

点点圈 提交于 2021-02-10 16:21:52

问题


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. 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:

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:

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'". 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'". 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??


回答1:


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. (Specifically, I don't recall if you can alias and into like this.)




回答2:


Answer ----->> so finally i was able to make it work, the trick was to add mydb.commit() after i call the procedure from 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)
    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. But, it is mentioned in .commit() documentation that

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.

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().



来源:https://stackoverflow.com/questions/53751358/stored-procedure-works-on-mysql-workbench-but-not-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!