数据库
首页 > 数据库> > mysql – 如何在存储过程中为预准备语句分配变量?

mysql – 如何在存储过程中为预准备语句分配变量?

作者:互联网

我已经整理了一个简单的存储过程,其中传递了两个参数以使其更具动态性.我已经在“前两位数和记录计数”部分准备了一份声明.

我不确定的是,我是否可以使用预准备语句使SET vTotalFT部分动态化.

目前我必须对表名和字段进行硬编码.我希望根据准备好的动态SQL语句分配我的vTotalFT变量,但我不确定语法.我的想法是,当我调用我的程序时,我可以告诉它哪个表和哪个字段用于分析.

CREATE PROCEDURE `sp_benfords_ft_digits_analysis`(vTable varchar(255), vField varchar(255))
    SQL SECURITY INVOKER
BEGIN

    -- Variables
    DECLARE vTotalFT int(11);

    -- Removes existing table
    DROP TABLE IF EXISTS analysis_benfords_ft_digits;

    -- Builds base analysis table
    CREATE TABLE analysis_benfords_ft_digits
    (
        ID int(11) NOT NULL AUTO_INCREMENT,
        FT_Digits int(11),
        Count_of_Records int(11),
        Actual decimal(18,3),
        Benfords    decimal(18,3),
        Difference Decimal(18,3),
        AbsDiff decimal(18,3),
        Zstat decimal(18,3),
        PRIMARY KEY (ID),
        KEY id_id (ID)
    );

    -- First Two Digits and Count of Records
    SET @s = concat('INSERT INTO analysis_benfords_ft_digits
                        (FT_Digits,Count_of_Records)
                            select substring(cast(',vField,' as char(50)),1,2) as FT_Digits, count(*) as Count_of_Records
                            from ',vTable,'
                            where ',vField,' >= 10
                            group by 1');

    prepare stmt from @s;
    execute stmt;
    deallocate prepare stmt;

    SET vTotalFT = (select sum(Count_of_Records) from
                            (select substring(cast(Gross_Amount as char(50)),1,2) as FT_Digits, count(*) as Count_of_Records
                                from supplier_invoice_headers
                                where Gross_Amount >= 10
                                group by 1) a);


    -- Actual
    UPDATE analysis_benfords_ft_digits
    SET Actual = Count_of_Records / vTotalFT;

    -- Benfords
    UPDATE analysis_benfords_ft_digits
    SET Benfords = Log(1 + (1 / FT_Digits)) / Log(10);

    -- Difference
    UPDATE analysis_benfords_ft_digits
    SET Difference = Actual - Benfords;

    -- AbsDiff
    UPDATE analysis_benfords_ft_digits
    SET AbsDiff = abs(Difference);

    -- ZStat
    UPDATE analysis_benfords_ft_digits
    SET ZStat = cast((ABS(Actual-Benfords)-IF((1/(2*vTotalFT))<ABS(Actual-Benfords),(1/(2*vTotalFT)),0))/(SQRT(Benfords*(1-Benfords)/vTotalFT)) as decimal(18,3));

解决方法:

首先,要使用动态表/列名称,您需要使用字符串/ Prepared Statement,就像您对@s的第一个查询一样.接下来,要从查询中获取COUNT()的返回值,您需要使用SELECT .. INTO @vTotalFT.

以下应该是您所需要的:

SET @vTotalFTquery = CONCAT('(select sum(Count_of_Records) INTO @vTotalFT from
                        (select substring(cast(', vField, ' as char(50)),1,2) as FT_Digits, count(*) as Count_of_Records
                            from ', vTable, '
                            where ', vField, ' >= 10
                            group by 1) a);');
PREPARE stmt FROM @vTotalFTquery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

请注意:变量名称已从vTotalFT更改为@vTotalFT.没有@它似乎没有用.而且,变量@vTotalFT在查询之外/之前声明时不起作用,因此如果遇到错误或空结果可能是原因.

标签:mysql,prepared-statement,dynamic-sql
来源: https://codeday.me/bug/20190626/1289338.html