【问题标题】:postgresql Convert array type from a non recurcive termepostgresql 从非递归术语转换数组类型
【发布时间】:2019-10-11 11:03:51
【问题描述】:

我正在处理递归查询,并且正在处理存储在 varchar(90) 列中的 guid。但是在使用 Postgres 11.1 时,我从 pgAdmin 得到了一个强制转换类型异常

我被困住了,我不知道我能做些什么来解决这个问题,如果有人可以帮助我的话。

https://docs.postgresql.fr/8.4/queries-with.html

Postgres CTE : type character varying(255)[] in non-recursive term but type character varying[] overall

with recursive sousSujet(typerefin,coderefin,typerefout,coderefout,type,profondeur,chemin, boucle) as (

    SELECT p.typerefin, p.coderefin, p.typerefout , p.coderefout , p.type,1, ARRAY[p.coderefout]::varchar(90)[] ,false  
    FROM relation p
    WHERE p.coderefin='2019094070' and p.typerefin='PROJET'

    --union all     
    union

    SELECT p.typerefin, p.coderefin, pr.typerefout, pr.coderefout, p.type ,pr.profondeur+1,
        --chemin || pr.coderefout,pr.coderefout = ANY(pr.chemin)
        chemin::varchar(90)[] || pr.coderefout,pr.coderefout = ANY(pr.chemin::varchar(90)[])
    FROM relation p,sousSujet pr
    -- WHERE p.coderefin = pr.coderefout    
    WHERE p.coderefin = pr.coderefout AND NOT pr.boucle and pr.profondeur < 10
)
SELECT typerefin,coderefin,typerefout,coderefout,type,profondeur
FROM sousSujet 
order by coderefout limit 20
ERROR:  ERREUR:  dans la requête récursive « soussujet », la colonne 7 a le type character varying(90)[] dans le terme non
récursif mais le type global character varying[]
LINE 3: ...oderefin, p.typerefout , p.coderefout , p.type,1, ARRAY[p.co...
                                                             ^
HINT:  Convertit la sortie du terme non récursif dans le bon type.

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    最简单的方法是将所有内容转换为文本,方法是在锚查询中使用ARRAY[p.coderefout::text],在递归查询中使用chemin::text || pr.coderefout。无需将所有内容都转换为数组

    with recursive sousSujet(typerefin,coderefin,typerefout,coderefout,type,profondeur,chemin, boucle) as (
    
        SELECT p.typerefin, p.coderefin, p.typerefout, p.coderefout, p.type, 1,
               ARRAY[p.coderefout::text], false  
        FROM relation p
        WHERE p.coderefin='2019094070' and p.typerefin='PROJET'
    
        union all 
    
        SELECT p.typerefin, p.coderefin, pr.typerefout, pr.coderefout, p.type ,pr.profondeur+1,
               chemin::text|| pr.coderefout,
               pr.coderefout = ANY(pr.chemin)
        FROM relation p
          join sousSujet pr 
            on p.coderefin = pr.coderefout 
           AND NOT pr.boucle 
           and pr.profondeur < 10
    )
    SELECT typerefin,coderefin,typerefout,coderefout,type,profondeur
    FROM sousSujet 
    order by coderefout limit 20
    

    【讨论】:

    • 感谢您的回答,它基本上是我想要达到的最干净的查询。最后,我能做的最干净的事情是投射这两个元素` - ARRAY[p.coderefout]::varchar(90)[] - (chemin|| pr.coderefout)::varchar(90)[] `“: :text" 不起作用,但正如你所说,我不需要投射其他。谢谢你
    【解决方案2】:

    错误抱怨该术语

    ARRAY[p.coderefout]::varchar(90)[]
    

    在非递归部分有varchar(90)[]类型,但对应的表达式

    chemin::varchar(90)[] || pr.coderefout
    

    在递归部分有类型varchar[]

    这是因为数组连接运算符||去掉了类型修饰符:

    SELECT '{a,b,c}'::varchar(90)[] || 'd'::varchar(90) \gdesc
    
      Column  |        Type         
    ----------+---------------------
     ?column? | character varying[]
    (1 row)
    

    您必须在连接的结果中添加显式转换:

    (chemin || pr.coderefout)::varchar(90)[]
    

    为了避免这样的烦恼,不要在那里使用类型修饰符。我只使用varchar 或更短的,但同义词text。无论如何,您并没有在最终结果中使用该列。

    【讨论】:

    • 感谢您的精彩解释,我明白了一些东西,它有效,再次感谢您!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 2016-03-08
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 2015-08-25
    • 1970-01-01
    相关资源
    最近更新 更多