简体   繁体   English

mysql存储过程group_concat为游标中的选择返回null

[英]mysql stored procedure group_concat returning null for select in cursor

I have a stored procedure where I'm looping through results in a cursor. 我有一个存储过程,在其中遍历游标中的结果。 The issue I'm having is the license_attributes value is always null when it shouldn't be. 我遇到的问题是license_attributes值在不应该为null时始终为null。 If I execute the select statement outside the stored procedure, or as a debug execute the select statement outside the cursor in the stored procedure, I get the results I'm expecting (not null) 如果我在存储过程之外执行select语句,或者在调试时在存储过程中的游标之外执行select语句,则会得到期望的结果(不为null)

This is the part of the select that is always returning null in the cursor: 这是select的一部分,它总是在游标中返回null:

        (SELECT 
            CONCAT('{""',sf.Asset_Attribute__c.Type__c,'"": {',GROUP_CONCAT(
            '""',sf.Asset_Attribute__c.Key__c,'"":""',LOWER(sf.Asset_Attribute__c.Value__c),'""'
            ),'}}')
            FROM 
                sf.Asset_Attribute__c 
            WHERE 
                sf.Asset_Attribute__c.Asset__c = license_id
            GROUP BY sf.Asset_Attribute__c.Asset__c) AS `license_attributes`

Here is the section of the stored proc: 这是存储过程的部分:

    GETCLOUDACCOUNTS:BEGIN

    DECLARE no_more_cloud_accounts_records boolean DEFAULT FALSE;

    DECLARE company VARCHAR(255) DEFAULT null;
    DECLARE license_status VARCHAR(50) DEFAULT null;
    DECLARE license_id VARCHAR(18) DEFAULT null;
    DECLARE cloud_owner_email VARCHAR(255) DEFAULT null;
    DECLARE entitlement_plan VARCHAR(255) DEFAULT null;
    DECLARE role VARCHAR(500) DEFAULT null;
    DECLARE is_trial BOOLEAN DEFAULT false;
    DECLARE license_attributes VARCHAR(2000) DEFAULT null;
    DECLARE zuora_account_id VARCHAR(100) DEFAULT '';
    DECLARE zuora_account_number VARCHAR(50) DEFAULT null;
    DECLARE zuora_account_status VARCHAR(50) DEFAULT null;
    DECLARE zuora_account_last_invoice_date DATETIME DEFAULT null;
    DECLARE has_active_subscriptions BOOLEAN DEFAULT false;

    DECLARE cloud_accounts_cursor CURSOR FOR 
        SELECT
            (SELECT `sf`.`Contact`.`CompanyName__c` FROM `sf`.`Contact` WHERE `sf`.`Asset`.`ContactId`=`sf`.`Contact`.`Id`) AS `company`,
            `sf`.`License_Key_Association__c`.`License_Key_Status__c` AS `license_status`,
            `sf`.`License_Key_Association__c`.`License_Key__c` AS `license_id`,
            `sf`.`Asset`.`ContactEmail__c` AS `cloud_owner_email`,
            (SELECT `sf`.`Contact`.`CloudEntitlementPlan__c` FROM `sf`.`Contact` WHERE `sf`.`Asset`.`ContactId`=`sf`.`Contact`.`Id`) AS `entitlement_plan`,
            `sf`.`License_Key_Association__c`.`Role__c` AS `role`,
            IF( (SELECT `sf`.`Product2`.`IsCommercial__c` FROM `sf`.`Product2` WHERE `sf`.`Product2`.`Id`=`sf`.`Asset`.`Product2Id`) = 0,true,false ) AS `is_trial`,
            (SELECT 
                CONCAT('{""',sf.Asset_Attribute__c.Type__c,'"": {',GROUP_CONCAT(
                '""',sf.Asset_Attribute__c.Key__c,'"":""',LOWER(sf.Asset_Attribute__c.Value__c),'""'
                ),'}}')
                FROM 
                    sf.Asset_Attribute__c 
                WHERE 
                    sf.Asset_Attribute__c.Asset__c = license_id
                GROUP BY sf.Asset_Attribute__c.Asset__c) AS `license_attributes`
        FROM
            `sf`.`License_Key_Association__c`
        LEFT JOIN `sf`.`Asset`
            ON `sf`.`License_Key_Association__c`.`License_Key__c` = `sf`.`Asset`.`Id` 
        JOIN `sf`.`Contact`
            ON `sf`.`Contact`.`Id` = `sf`.`License_Key_Association__c`.`Contact__c`
        WHERE
            `sf`.`Contact`.`ExternalID__c`='someexternalidhere';

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_cloud_accounts_records = true;
        SELECT
            (SELECT `sf`.`Contact`.`CompanyName__c` FROM `sf`.`Contact` WHERE `sf`.`Asset`.`ContactId`=`sf`.`Contact`.`Id`) AS `company`,
            `sf`.`License_Key_Association__c`.`License_Key_Status__c` AS `license_status`,
            `sf`.`License_Key_Association__c`.`License_Key__c` AS `license_id`,
            `sf`.`Asset`.`ContactEmail__c` AS `cloud_owner_email`,
            (SELECT `sf`.`Contact`.`CloudEntitlementPlan__c` FROM `sf`.`Contact` WHERE `sf`.`Asset`.`ContactId`=`sf`.`Contact`.`Id`) AS `entitlement_plan`,
            `sf`.`License_Key_Association__c`.`Role__c` AS `role`,
            IF( (SELECT `sf`.`Product2`.`IsCommercial__c` FROM `sf`.`Product2` WHERE `sf`.`Product2`.`Id`=`sf`.`Asset`.`Product2Id`) = 0,true,false ) AS `is_trial`,
            (SELECT 
                CONCAT('{""',sf.Asset_Attribute__c.Type__c,'"": {',GROUP_CONCAT(
                '""',sf.Asset_Attribute__c.Key__c,'"":""',LOWER(sf.Asset_Attribute__c.Value__c),'""'
                ),'}}')
                FROM 
                    sf.Asset_Attribute__c 
                WHERE 
                    sf.Asset_Attribute__c.Asset__c = license_id
                GROUP BY sf.Asset_Attribute__c.Asset__c) AS `license_attributes`
        FROM
            `sf`.`License_Key_Association__c`
        LEFT JOIN `sf`.`Asset`
            ON `sf`.`License_Key_Association__c`.`License_Key__c` = `sf`.`Asset`.`Id` 
        JOIN `sf`.`Contact`
            ON `sf`.`Contact`.`Id` = `sf`.`License_Key_Association__c`.`Contact__c`
        WHERE
            `sf`.`Contact`.`ExternalID__c`=@p_externalId;

    OPEN cloud_accounts_cursor;
    CLOUDACCOUNTSLOOP: loop

        fetch cloud_accounts_cursor into company, license_status, license_id, cloud_owner_email, entitlement_plan, role, is_trial, license_attributes;

        IF is_trial = true THEN
            SET has_active_subscriptions = true;
        END IF;

        SET zuora_account_id = `z`.`getZAccountId`(cloud_owner_email);

        IF zuora_account_id IS NOT NULL THEN
            SELECT `accountNumber`,`status`,`lastInvoiceDate` INTO zuora_account_number,zuora_account_status,zuora_account_last_invoice_date FROM zuora.Account WHERE id=zuora_account_id;

            IF has_active_subscriptions = false THEN
                SET has_active_subscriptions = (SELECT IF((SELECT COUNT(*) FROM `z`.`RatePlan`
                    RIGHT JOIN `z`.`ProductRatePlan` ON `z`.`RatePlan`.`productRatePlanId` = `z`.`ProductRatePlan`.`id`
                    LEFT JOIN `z`.`Subscription` ON `z`.`RatePlan`.`subscriptionId` = `z`.`Subscription`.`id`
                    WHERE
                    `z`.`ProductRatePlan`.`wowzaRatePlanCode__c` IN ( (SELECT `code` FROM `z`.`zCloudRatePlanCodes`) )
                    AND `z`.`Subscription`.`status` = 'Active'
                    AND `z`.`Subscription`.`accountId` = zuora_account_id ) > 0, true, false));
            END IF;
        END IF;

        REPLACE INTO `sf`.`zCloudAccounts` (`user_email`,`company`,`license_status`,`license_id`,`cloud_owner_email`,`entitlement_plan`,`role`,`is_trial`,`attributes`,`zuora_account_id`,`zuora_account_number`,`zuora_account_status`,`zuora_account_last_invoice_date`,`has_active_subscriptions`) VALUES(@p_userEmail,company,license_status,license_id,cloud_owner_email,entitlement_plan,role,is_trial,license_attributes,zuora_account_id,zuora_account_number,zuora_account_status,zuora_account_last_invoice_date,has_active_subscriptions);

        IF no_more_cloud_accounts_records THEN
            CLOSE cloud_accounts_cursor;
            LEAVE CLOUDACCOUNTSLOOP;
        end if;

    END LOOP CLOUDACCOUNTSLOOP;

END GETCLOUDACCOUNTS;

If I execute the full select stateout outside of GETCLOUDACCOUNTS block, I get the results I expect: 如果我在GETCLOUDACCOUNTS块之外执行完全选择状态,则会得到预期的结果:

company, license_status, license_id, cloud_owner_email, entitlement_plan, role, is_trial, license_attributes
Test Company, Active, 02iq0000000jKgMAAU, myemail@email.com, Standard, Owner, 0, {""cloud"": {""cloud_num_247_t_streams"":""0"",""cloud_num_247_p_streams"":""0""}}
Test Company, Active, 02iq0000000xlBBAAY, otheremail@email.com, Standard, Admin;wcl_admin;wcl_support, 0, {""cloud"": {""cloud_num_247_t_streams"":""1"",""cloud_num_247_p_streams"":""1"",""test_attribute"":""true"",""api_access"":""true""}}

But the results inside the block show license_attributes as null: 但是该块内的结果显示license_attributes为null:

company, license_status, license_id, cloud_owner_email, entitlement_plan, role, is_trial, license_attributes
Test Company, Active, 02iq0000000jKgMAAU, myemail@email.com, Standard, Owner, 0, null
Test Company, Active, 02iq0000000xlBBAAY, otheremail@email.com, Standard, Admin;wcl_admin;wcl_support, 0, null

Any help is greatly appreciated! 任何帮助是极大的赞赏!

I suspect the issue is related to the procedure variable license_id . 我怀疑该问题与过程变量license_id

The correlated subselect in the SELECT list includes SELECT列表中的相关子选择包括

 WHERE sf.Asset_Attribute__c.Asset__c = license_id
                                        ^^^^^^^^^^

Local variables take precedence over column references. 局部变量优先于列引用。 Since license_id is declared as a variable within the code block, 由于license_id在代码块中被声明为变量,

 DECLARE license_id VARCHAR(18) DEFAULT null;

the reference to license_id in the SELECT statement is a reference to that procedure variable. SELECT语句中对license_id的引用是对该过程变量的引用。

Outside the code block, there likely is not a local variable named license_id . 在代码块之外,可能没有名为license_id的局部变量。 So that same SQL SELECT statement, that reference to license_id is not a reference to a variable, but a reference to a column. 因此,与同一条SQL SELECT语句一样,对license_id的引用不是对变量的引用,而是对列的引用。

I haven't traced through all of the logic, or the contents of license_id variable. 我没有跟踪所有逻辑,也没有跟踪license_id变量的内容。 But I suspect that explains the difference in the behavior observed with the statement, executed inside the code block vs outside the block. 但是我怀疑这解释了在代码块内部与在代码块外部执行的语句所观察到的行为的差异。

You can COALESCE to take care of NULL values in your GROUP_CONCAT 您可以COALESCE来处理GROUP_CONCAT中的NULL值

COALESCE(`YourColumnName`,'')

You can also use a significantly different string to show you where the NULL value is coming from, so that you can then fix the query. 您还可以使用截然不同的字符串来显示NULL值来自何处,以便随后可以修复查询。

COALESCE(`YourColumnName`,'**UNEXPECTED NULL**')

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

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