存储函数和动态 where 子句和 json_object 错误修复

问题描述 投票:0回答:1

我在mysql 8.0中定义了一个存储函数: 但是每当我尝试使用下面提到的调用来调用该函数时,它都会抛出一条错误消息,#1582 - 调用本机函数“JSON_OBJECT”时参数计数不正确。如何解决?此外,如何使用带有动态 where 子句的准备语句定义选择查询,其中 where 条件的键和值都是动态的?

BEGIN
    DECLARE ssoId VARCHAR(255) DEFAULT NULL;
    DECLARE emailId VARCHAR(255) DEFAULT NULL;
    DECLARE instructorId VARCHAR(255) DEFAULT NULL;
    DECLARE firstName VARCHAR(255) DEFAULT NULL;
    DECLARE lastName VARCHAR(255) DEFAULT NULL;
    DECLARE createdAt TIMESTAMP DEFAULT NULL;
    DECLARE updatedAt TIMESTAMP DEFAULT NULL;
    DECLARE storedUser JSON DEFAULT NULL;
    
    SET ssoId = JSON_EXTRACT(user,'$.ssoId');
    SET emailId = JSON_EXTRACT(user,'$.email');
    SET firstName = JSON_EXTRACT(user,'$.firstName');
    SET lastName = JSON_EXTRACT(user,'$.lastName');
    SET createdAt = JSON_EXTRACT(user,'$.createdAt');
    SET updatedAt = JSON_EXTRACT(user,'$.updatedAt');
    IF JSON_EXTRACT(user,'$.instructorId') IS NOT NULL THEN
        SET instructorId = JSON_EXTRACT(user,'$.instructorId');
    ELSE 
        SET instructorId = JSON_EXTRACT(user,'$.instructorStudentId');
    END IF;
    
    IF ssoId IS NOT NULL THEN
        SELECT JSON_OBJECT(
            "id", id,
            "sso_id", sso_id,
            "email", email,
            "instructor_id", instructor_id,
            "first_name", first_name,
            "last_name", last_name,
            "source_created_at", source_created_at,
            "source_updated_at", source_updated_at)
        INTO storedUser FROM datahub.users WHERE sso_id = ssoId;
    ELSEIF instructorId IS NOT NULL THEN
        SELECT JSON_OBJECT(
            "id", id,
            "sso_id", sso_id,
            "email", email,
            "instructor_id", instructor_id,
            "first_name", first_name,
            "last_name", last_name,
            "source_created_at", source_created_at,
            "source_updated_at", source_updated_at)
        INTO storedUser FROM datahub.users WHERE instructor_id = instructorId;
    ELSEIF emailId IS NOT NULL THEN
        SELECT JSON_OBJECT(
            "id", id,
            "sso_id", sso_id,
            "email", email,
            "instructor_id", instructor_id,
            "first_name", first_name,
            "last_name", last_name,
            "source_created_at", source_created_at,
            "source_updated_at", source_updated_at)
        INTO storedUser FROM datahub.users WHERE email = emailId;
    END IF; 
    RETURN -1;
END;
mysql stored-procedures stored-functions mysql-function
1个回答
0
投票

我测试了你的功能,但我没有看到你描述的错误。

我确实看到了另一个问题。

JSON_EXTRACT() 的结果是一个 JSON 标量,而不是字符串。所以你会在它周围看到双引号,就像任何 JSON 标量字符串一样。

mysql> set @j = '{"key": "value"}';

mysql> select json_extract(@j, '$.key');
+---------------------------+
| json_extract(@j, '$.key') |
+---------------------------+
| "value"                   |
+---------------------------+

这自然不会匹配您表中的任何值,因为我假设它们不包含双引号字符。

您可以使用 JSON_UNQUOTE() 获取字符串值:

mysql> select json_unquote(json_extract(@j, '$.key'));
+-----------------------------------------+
| json_unquote(json_extract(@j, '$.key')) |
+-----------------------------------------+
| value                                   |
+-----------------------------------------+

您必须在提取 JSON 字段的每一行上执行此操作。

您询问了如何运行动态 SQL 查询。您不能在 MySQL 存储函数中执行此操作,因为存储函数可能会从准备好的查询本身执行。

https://dev.mysql.com/doc/refman/8.0/en/stored-program-restrictions.html 说:

SQL 预处理语句(

PREPARE
EXECUTE
DEALLOCATE PREPARE
)可以用在存储过程中,但不能用在存储函数或触发器中。因此,存储函数和触发器不能使用动态 SQL(您将语句构造为字符串然后执行它们)。

© www.soinside.com 2019 - 2024. All rights reserved.