sql - 用于多合一动态查询的 PL/pgSQL

标签 sql postgresql database-design plpgsql dynamic-sql

我正在使用 PostigreSQL10。我有一个一体化查询,用户可以在其中选择类别样式、事件、区域的非标准组合来搜索结构。请记住,类别样式、事件、区域位于不同的表中。

我想避免使用多个 IFJOIN。我还想避免查询计划器每次都为错误的参数组合缓存错误的计划以及后续的查询重新编译。所以我必须使用动态SQL。

要在 PostgreSQL 中获取动态 SQL,我必须使用 PL/pgSQL。但是,根据其文档

to generate dynamic commands inside your PL/pgSQL functions, that is, commands that will involve different tables or different data types each time they are executed. PL/pgSQL's normal attempts to cache plans for commands will not work in such scenarios. To handle this sort of problem, the EXECUTE statement is provided. Also, there is no plan caching for commands executed via EXECUTE. Instead, the command is always planned each time the statement is run. If multiple rows are returned, only the first will be assigned to the INTO variable - here

SQL commands that appear directly in a PL/pgSQL function must refer to the same tables and columns on every execution; that is, you cannot use a parameter as the name of a table or column in an SQL command. To get around this restriction, you can construct dynamic commands using the PL/pgSQL EXECUTE statement — at the price of performing new parse analysis and constructing a new execution plan on every execution - here

因此,我猜想 PL/pgSQL 不是适合我的情况的工具,因为我有多个表。

我的问题是:PL/pgSQL 实际上不适合我的情况,还是我遗漏了什么? 子问题:如果不合适,我如何为 postgreSQL 语法动态 sql,我找不到任何教程。

谢谢

最佳答案

能否请您发布一些表定义和您要执行的操作的示例查询?我不是 100% 确定您要做什么,但是有几种使用存储过程/函数的“动态”SQL 形式:

  1. 创建一个接受输入参数(即 categoryType、styleId、eventName、areaId)的函数,并将这些值插入到“静态”SQL 请求中。以下是您的案例的示例查询片段:
SELECT *
FROM category cat
INNER JOIN style st ON cat.styleid = style.id
WHERE (cat.categoryType = pCategoryType OR pCategoryType IS NULL)
AND (st.id = pStyleId OR pStyleId IS NULL)

这是一个真实的例子:

CREATE OR REPLACE FUNCTION SP_IGLGetItem(
    pItemId INTEGER
) 
RETURNS TABLE(
    ItemId INTEGER,
    ItemName VARCHAR(100),
    ItemCategory CHAR(2) 
AS
$$
BEGIN
    RETURN QUERY
    SELECT i.ItemId, i.ItemName, i.ItemCategory
    FROM Item i
    WHERE (i.ItemId = pItemId OR pItemId IS NULL) -- Return single item (if specified, otherwise return all)
    ;
END;
$$
LANGUAGE 'plpgsql';
  1. 构建一个字符串,其中包含您要根据不同条件、参数值等动态执行的 SQL。这是尽可能动态的。

  2. 根据输入参数的值有条件地运行不同的“静态”SQL 语句。

这些符合您的情况吗?

PL/PGSQL 只是用于在 Postgres 中编写存储过程/函数的语言。如果您确实需要动态 SQL 生成,那么最好的办法是使用 PL/PGSQL 编写一个函数。

另一种选择是在客户端应用程序中动态生成所需的 SQL,然后直接提交该 SQL 以供执行。

关于sql - 用于多合一动态查询的 PL/pgSQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48216935/

相关文章:

java - jSecurity JDBCRealm SQL 设置

postgresql - 将字符串分数转换为 float

database - Unix 域套接字 "/tmp/.s.PGSQL.5432"上的 Postgres 连接?

mysql - (MySql) 选择查询在 WHERE 和 AND 条件下返回空行

mysql - 从本地导入 mysql 转储到 SSH

sql - 生成 SQL 以更新主键

sql - postgresql - json 对象的键/值查找

sql - 用户事件的数据库结构是否正确?

c# - 数据库双连接关系插入问题

ruby-on-rails - rails : dynamic columns/attributes on models?