在SELECT语句中,根据另一个列的数据类型设置一个字面量列的值

后端开发 2026-07-09

我想基于另一列值的数据类型(假设该列的值是字符串或数字),动态地把一个文本列的字面量设置为字符串或数字,以便在SELECT语句中使用。例如,我想生成一个 SELECT 'a' AS sortColumn FROM g_nodeSELECT 1 AS sortColumn FROM g_node 的语句。

我有一个JSONB properties 列,其元素可以是数字或字符串。下面的CASE语句包含我想要的逻辑,区别在于第二个WHEN子句中我想把 'b' 改成数字1:

SELECT (jsonb_typeof(properties->'[variableElement]'))::text, 
    CASE (jsonb_typeof(properties->'[variableElement]'))::text
       WHEN 'string' THEN 'a'
       WHEN 'number' THEN 'b'
    END AS sortColumn
FROM g_node

PostgreSQL对下列内容不予接受,因为它要求CASE子句中的所有值都属于相同的类型(该SQL无法工作):

SELECT (jsonb_typeof(properties->'[variableElement]'))::text, 
    CASE (jsonb_typeof(properties->'[variableElement]'))::text
       WHEN 'string' THEN 'a'
       WHEN 'number' THEN 1
    END AS sortColumn
FROM g_node

因为CASE语句没成功,我想到或许可以创建一个变量,在动态生成的查询中使用该值,但下面的查询返回一个表,其列名为 result_val,行值为 'a' as sortColumn,类型为字符串:

CREATE OR REPLACE FUNCTION dynamic_select()
RETURNS TABLE(result_val TEXT) AS 
$$
DECLARE
    column_name TEXT := (SELECT
    CASE (jsonb_typeof(properties->'name'))::text
       WHEN 'string' THEN ('''a'' as sortColumn')::text
       WHEN 'number' THEN ('1 as sortColumn')::text
    END as sortColumn
    FROM g_node LIMIT 1);
BEGIN
    RETURN QUERY EXECUTE format('SELECT %L FROM g_node', column_name);
END;
$$ LANGUAGE plpgsql;

-- Usage
SELECT * FROM dynamic_select();

有没有其他用SQL的可行解决方案?理想情况下,如果不是太复杂,我想尽量在SQL内完成;否则我将使用Python脚本来构建查询。

解决方案

PostgreSQL对下列内容不予接受,因为它要求CASE子句中的所有值都属于相同的类型

是的。这不仅是Postgres的问题,也不仅是 CASE 子句的问题,而是SQL工作方式的一个根本特性。在每个查询中,返回的关系中的所有列都必须具有固定且预先确定的类型,随后返回的所有行必须包含恰好属于这些类型的值。

你可能需要运行两个独立的查询:

SELECT 1::int    AS "sortColumn" FROM g_node WHERE jsonb_typeof(properties->'[variableElement]') = 'number';
SELECT 'a'::text AS "sortColumn" FROM g_node WHERE jsonb_typeof(properties->'[variableElement]') = 'string';

鉴于你已经在使用JSON,你也可能能够编写并执行一个返回类型为 json(b) 的列的单个查询,但是我还不太确定你到底想要什么。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章