针对JSON键投掷的准备陈述“必须出现在小组中”条款。在使用PDO的PostgreSQL中

发布于 2025-01-31 07:57:26 字数 1144 浏览 1 评论 0原文

我正在尝试通过JSON Keys动态分组,以找到平均答案。

select
   tbl.data->>'Example' as response,
   count(tbl.data->>'Example') as total
from table tbl
group by tbl.data->>'Example'
order by total
limit 1

此查询在PostgreSQL内部运行时可以正常工作,并且我得到了预期的结果:

|     response   |  total  |
|--------------------------|
|  Hello World   |    4    |

当我不知道钥匙时,问题现在就会发生。它们动态创建,因此我需要循环浏览它们。

$sql = <<<END
    select
       tbl.data->>? as response,
       count(tbl.data->>?) as total
    from table tbl
    group by tbl.data->>?
    order by total
    limit 1
END;

$stmt = (new \PDO(...))->Prepare($sql);
$stmt->execute(array_fill(1, 3, 'Example'));
$stmt->fetch(\PDO::FETCH_ASSOC);

“示例”来自用户输入。 JSON由用户创建,键可能是任何东西。在这种情况下,它进行了硬编码,但我运行了单独的SQL查询,以获取所有键和循环循环:

但是我总是会收到以下错误:

tbl.data必须通过子句出现在组中或用于聚合函数

,我认为这是因为准备好的语句将列视为数据,但是此信息来自用户输入,因此我需要使用准备好的语句。

select json_object_keys(data) as keys from table

有什么猜测我如何解决这个问题?

I am trying to dynamically group by json keys to find the average answer.

select
   tbl.data->>'Example' as response,
   count(tbl.data->>'Example') as total
from table tbl
group by tbl.data->>'Example'
order by total
limit 1

This Query works fine when it is ran inside PostgreSQL and I get my expected result:

|     response   |  total  |
|--------------------------|
|  Hello World   |    4    |

The issue now occurs when I don't know the keys. They're dynamically created and thus I need to loop over them.

$sql = <<<END
    select
       tbl.data->>? as response,
       count(tbl.data->>?) as total
    from table tbl
    group by tbl.data->>?
    order by total
    limit 1
END;

$stmt = (new \PDO(...))->Prepare($sql);
$stmt->execute(array_fill(1, 3, 'Example'));
$stmt->fetch(\PDO::FETCH_ASSOC);

'Example' comes from user input. The JSON is created by the user, the keys could be anything. In this case, its hard-coded but I run a seperate SQL query to get all the keys and loop over them:

But I always get the following error:

tbl.data must appear in the GROUP BY clause or be used in an aggregate function

Now, I assume this is because of the prepared statement treating the column as data but this information derives from user input so I need to use prepared statements.

select json_object_keys(data) as keys from table

Any guess to how I can resolve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

油焖大侠 2025-02-07 07:57:26

我不知道PHP。但是从这个链接(


CREATE OR REPLACE FUNCTION find_answer (_key text)
    RETURNS json
    AS $
DECLARE
    is_exists boolean;
    _sql text;
    _return json;
BEGIN
    _sql := $sql$
    SELECT
        row_to_json(cte.*)
    FROM (
        SELECT
            tbl.data ->> $1 AS response,
            count(tbl.data ->> $1) AS total
        FROM
            tbl
        GROUP BY
            1
        ORDER BY
            total DESC
        LIMIT 1) cte $sql$;
    SELECT
        (data[_key] IS NULL) INTO is_exists
    FROM
        tbl;
    IF is_exists THEN
        RAISE EXCEPTION '% not exists.', _key;
    ELSE
        RAISE NOTICE '% sql', _sql;
        EXECUTE _sql
        USING _key INTO _return;
        RETURN _return;
    END IF;
END
$
LANGUAGE plpgsql;

select *从find_answer('example');


关于准备的语句

准备的陈述仅在电流的持续时间内持续
数据库会话。会话结束时,准备的语句是
被遗忘了,因此必须重新使用它,然后再使用。这也是如此
意味着一个准备好的语句不能由多个
同时数据库客户端;但是,每个客户都可以创建他们的
自己准备使用的陈述。准备的陈述可以手动
使用DealLocate命令进行清理。

I don't know Php. But from this link(https://kb.objectrocket.com/postgresql/postgres-stored-procedure-call-in-php-1475), seems it's pretty ok to use functions in php.

demo


CREATE OR REPLACE FUNCTION find_answer (_key text)
    RETURNS json
    AS $
DECLARE
    is_exists boolean;
    _sql text;
    _return json;
BEGIN
    _sql := $sql$
    SELECT
        row_to_json(cte.*)
    FROM (
        SELECT
            tbl.data ->> $1 AS response,
            count(tbl.data ->> $1) AS total
        FROM
            tbl
        GROUP BY
            1
        ORDER BY
            total DESC
        LIMIT 1) cte $sql$;
    SELECT
        (data[_key] IS NULL) INTO is_exists
    FROM
        tbl;
    IF is_exists THEN
        RAISE EXCEPTION '% not exists.', _key;
    ELSE
        RAISE NOTICE '% sql', _sql;
        EXECUTE _sql
        USING _key INTO _return;
        RETURN _return;
    END IF;
END
$
LANGUAGE plpgsql;

then call it. select * from find_answer('example');


about Prepared statements

Prepared statements only last for the duration of the current
database session. When the session ends, the prepared statement is
forgotten, so it must be recreated before being used again. This also
means that a single prepared statement cannot be used by multiple
simultaneous database clients; however, each client can create their
own prepared statement to use. Prepared statements can be manually
cleaned up using the DEALLOCATE command.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文