繁体   English   中英

从 PYTHON 调用时,MySQL 存储过程 DELETE 不起作用

[英]MySQL Stored Procedure DELETE not working when called from PYTHON

我有一个 MySQL 存储过程,它将数据库记录从指定的 INTERVAL 备份到 csv 文件,然后删除相同的记录。

当我从 phpMyAdmin 或 MySQL Workbench 调用程序时,它运行良好。 它创建存档文件,并删除记录。

但是,当我从 Python 应用程序中调用存储过程时,它将创建存档文件,但不会删除记录。

input 和 session 变量也是 output 到特定的日志文件进行调试。 这一切都很好,我在日志文件中看到了我的期望。

这是我的存储过程:

CREATE DEFINER=`ctuser`@`%` PROCEDURE `sp_TableDump`(
    IN db VARCHAR(50), 
    IN tbl VARCHAR(50),
    IN dateCol VARCHAR(20),
    IN intrvl VARCHAR(20),
    IN allowArchive boolean,
    IN allowPurge boolean
)
BEGIN
    #I know my input fields are correct because of the log1.log created below
    SELECT db, tbl, dateCol, intrvl, allowArchive, allowPurge into outfile '/var/lib/mysql-files/log1.log';

    SET @defMaxLength = (SELECT @@group_concat_max_len);#get the default group_concat limit    
    SET SESSION group_concat_max_len = 1000000;#set the Group Concat Max Limit for tables with a lot of columns

    SET @date = CURDATE();
    SET @path = CONCAT('/var/lib/mysql-files/', db, '.', tbl, '_ARCHIVE_', @date, '.csv');

    SET @tbl = CONCAT(db, '.', tbl);  

    SET @where = CONCAT(' WHERE ', dateCol, ' < CURDATE() - INTERVAL ', intrvl);
    SET @orderBy = CONCAT(' ORDER BY ', dateCol); 

    #I know my session variables are correct because of the log2.log created below
    SELECT @date, @path, @tbl, @where, @orderBy into outfile '/var/lib/mysql-files/log2.log';

    IF allowArchive THEN    
        #I know we get in here because log2.log gets created            
        #archive the records
        #get the columns from the table
        SET @cols = (SELECT GROUP_CONCAT(QUOTE(`column_name`)) AS columns FROM information_schema.columns WHERE table_schema = db AND table_name = tbl);
        SET @colQry = CONCAT('(SELECT ', @cols, ')');      
        SET @outfileQry = CONCAT('(SELECT * FROM ', @tbl, @where, @orderBy, ' INTO OUTFILE \'', @path, 
                                '\' FIELDS ENCLOSED BY \'\\\'\' TERMINATED BY \'\t\' ESCAPED BY \'\' LINES TERMINATED BY \'\n\')');

        SET @outfileSQL = CONCAT(@colQry, ' UNION ALL ', @outfileQry);
        SELECT @cols, @colQry, @outfileQry, @outfileSQL into outfile '/var/lib/mysql-files/log2.log';

        PREPARE outStmt FROM @outfileSQL;
        EXECUTE outStmt;#This works every time 
        DEALLOCATE PREPARE outStmt;
    END IF;

    IF allowPurge THEN    
        #I know we get in here because log3.log gets created
        #delete the records
        SET @delSQL = CONCAT('DELETE FROM ', @tbl, @where);

        SELECT @delSQL into outfile '/var/lib/mysql-files/log3.log'; # @delSQL looks correct in log3.log

        PREPARE delStmt FROM @delSQL;        
        EXECUTE delStmt; # This does not seem to happen when I run in Python.  It works perfectly in MySQL Workbench or phpMyAdmin
        DEALLOCATE PREPARE delStmt;
    END IF;

    SET SESSION group_concat_max_len = @defMaxLength;#reset the default group_concat limit
END

这是 Python function:

def archiveAndDeleteRecords():
    log.info('Attempting to purge data older than ' + interval + ' from ' + db + '.' + tbl + " col: " + columnName)    
    dateTime = datetime.now().strftime("%Y%m%d%H%M%S")
    archivePath = "/mnt/Storage/DatabasePurge/" + db + "/"

    try:
        args = [db, tbl, columnName, interval, allowArchive, allowPurge] # The args look good in python and when passed to stored proc
        stProc = 'sp_TEST'
        log.info('calling stproc ' + stProc)
        log.info('args ' + str(args))
        result_args = cursor.callproc(stProc, args)
        conn.commit()
    except Exception as ex:
        log.error("Could not execute stored procedure!");
        log.error("error: " + str(sys.exc_info()[0]));
        log.error("exception: " + str(ex));
        traceback.print_tb(ex.__traceback__)

    return;

几个小时以来,我一直在用头撞墙。 任何帮助,将不胜感激。 谢谢。

这对我来说也很头疼,但我找到了解决方案。 一方面,您的存储过程必须在您的数据库中运行。 另一方面,在 python 中,您将使用 sqlalchemy 连接到相应的数据库。 注意:更新相应值的变量。

from sqlalchemy import create_engine

driver='ODBC Driver 17 for SQL Server'
engine = create_engine('mssql+pyodbc://{}:{}@{}/{}?driver={}'.format(user_name, password, server_name, database_name, driver))

query = ('exec name_stored_procedure @var1=\'{}\', @var2=\'{}\''.format(value1, value2))

with engine.begin() as conn:
    conn.execute(query)

使用 begin 方法将执行存储过程并将其提交到数据库,删除您想要的数据

暂无
暂无

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

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