通过 SQLAlchemy 将存储过程定义传递给 singlestore/memsql

Pass stored procedure definition to singlestore/memsql via SQLAlchemy

我在文件 stored_procedure.sql 中存储了一个存储过程 (ha)。如果我在 SQL 编辑器软件中打开这个文件,我可以定义过程并在 Python 或 SQL 中调用它。该过程如下所示:

CREATE OR REPLACE PROCEDURE 
test_proc (some_date VARCHAR(10)) 
RETURNS INT AS
  BEGIN
    INSERT INTO db.test
    -- join TABLE 1 and TABLE 2 for final results
    SELECT some_date;
RETURN 1;
END //
DELIMITER ;

但是,我希望 Python 能够读取过程文件,并将存储过程传递给数据库(如果存储过程得到更新但没有手动重新 运行 , 代码拾取程序的重新定义)。

当我将存储过程读入文本流并尝试执行时:

from sqlalchemy import create_engine
conn = create_engine(parameters_to_connect_to_database)
statement = open('stored_procedure.sql').read()

trans = conn.begin()
conn.execute(statement)
trans.commit()

conn.execute(statement) 的语法错误如下:

ProgrammingError: (pymysql.err.ProgrammingError) (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DELIMITER //\nCREATE OR REPLACE PROCEDURE

我知道 sql 脚本实际上没有语法错误,因为如果我在 sql 编辑器软件中,它可以手动运行。如果我将存储过程文件与其中包含 create table 或 insert into 语句的文件交换,则不会返回任何错误并且插入成功。

我如何编辑上面的文件以执行其中包含 SQL 语句的文件,以及其中写入存储过程的文件?

DELIMITER 不是 SQL 语句。它是一个命令,可帮助 MySQL shell 避免混淆关于如何解释 ; 当它出现在存储过程定义中时,存储过程定义本身是 CREATE PROCEDURE 语句的一部分。当 运行 shell 之外的 CREATE PROCEDURE 语句时,DELIMITER 不是必需的(或有效的)。

这失败了:

import sqlalchemy as sa

engine = sa.create_engine("mysql+pymysql://scott:tiger@localhost:3307/mydb")

drop_sp = "DROP PROCEDURE IF EXISTS test_proc"
create_sp = """\
CREATE DEFINER=`root`@`localhost` PROCEDURE `test_proc`()
BEGIN
   SELECT 'this is a test';
END //
DELIMITER ;
"""

with engine.begin() as conn:
    conn.exec_driver_sql(drop_sp)
    conn.exec_driver_sql(create_sp)

但这行得通

import sqlalchemy as sa

engine = sa.create_engine("mysql+pymysql://scott:tiger@localhost:3307/mydb")

drop_sp = "DROP PROCEDURE IF EXISTS test_proc"
create_sp = """\
CREATE DEFINER=`root`@`localhost` PROCEDURE `test_proc`()
BEGIN
   SELECT 'this is a test';
END
"""

with engine.begin() as conn:
    conn.exec_driver_sql(drop_sp)
    conn.exec_driver_sql(create_sp)