存储过程适用于 MySQL workbench,但不适用于 python
Stored procedure works on MySQL workbench, but not in python
我正在测试一个数据库,其中有 3 个 table,第 1 个存储用户信息,第 2 个存储不同城市的经纬度,还有第 3 个 table存储用户的位置及其到最近城市的距离。第三个 table 有一个来自其他两个 table 的主键的组合键。
我在 mysql workbench 中编写了一个存储过程,它接收 5 个变量,然后将数据插入到第 3 个 table 中,这里是使用一些随机变量的代码:
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);
它工作正常并插入 table,但是当我尝试使用来自 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))
它给出另一个错误说 "Unknown column 'Gilan' in 'field list'"。有趣的是,如果我手动将相同的数据插入 table,那么当我尝试从 python 调用该过程时,它会引发错误:"Duplicate entry '70440675-883' for key 'PRIMARY'"。所以它似乎试图插入 table,但它没有保存它!
有人可以告诉我我在这里做错了什么吗?
我的猜测可能是存储过程的第二个和第三个查询之间存在一些舍入问题。您可能会考虑完全消除第二个查询,并将第三个查询更改为如下内容:
SELECT location_id, ST_Distance_Sphere(@pt1, geopoint)/1000 AS distance
INTO @lmini, @mini
FROM locations
ORDER BY distance ASC
LIMIT 1;
*我说 "something like" 是因为我最近主要在 MSSQL 中工作,而在 MySQL 时我并没有做很多 SELECT INTO。 (具体的,我不记得你是否可以这样别名和进入。)
答案 ----->> 所以最后我能够让它工作,诀窍是在我从 python[=13= 调用过程后添加 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))
文档中没有提到我们需要使用 .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() 文档
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.
所以我的猜测是因为该过程试图操作数据库中的数据并且它是从 python 客户端调用的,所以我们需要在使用 .callproc() 之后使用 .commit()。
我正在测试一个数据库,其中有 3 个 table,第 1 个存储用户信息,第 2 个存储不同城市的经纬度,还有第 3 个 table存储用户的位置及其到最近城市的距离。第三个 table 有一个来自其他两个 table 的主键的组合键。 我在 mysql workbench 中编写了一个存储过程,它接收 5 个变量,然后将数据插入到第 3 个 table 中,这里是使用一些随机变量的代码:
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);
它工作正常并插入 table,但是当我尝试使用来自 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))
它给出另一个错误说 "Unknown column 'Gilan' in 'field list'"。有趣的是,如果我手动将相同的数据插入 table,那么当我尝试从 python 调用该过程时,它会引发错误:"Duplicate entry '70440675-883' for key 'PRIMARY'"。所以它似乎试图插入 table,但它没有保存它! 有人可以告诉我我在这里做错了什么吗?
我的猜测可能是存储过程的第二个和第三个查询之间存在一些舍入问题。您可能会考虑完全消除第二个查询,并将第三个查询更改为如下内容:
SELECT location_id, ST_Distance_Sphere(@pt1, geopoint)/1000 AS distance
INTO @lmini, @mini
FROM locations
ORDER BY distance ASC
LIMIT 1;
*我说 "something like" 是因为我最近主要在 MSSQL 中工作,而在 MySQL 时我并没有做很多 SELECT INTO。 (具体的,我不记得你是否可以这样别名和进入。)
答案 ----->> 所以最后我能够让它工作,诀窍是在我从 python[=13= 调用过程后添加 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))
文档中没有提到我们需要使用 .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() 文档
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.
所以我的猜测是因为该过程试图操作数据库中的数据并且它是从 python 客户端调用的,所以我们需要在使用 .callproc() 之后使用 .commit()。