Maison >base de données >tutoriel mysql >Pourquoi les colonnes de ma fonction renvoyant un ensemble sont-elles concaténées lorsqu'elles sont utilisées dans une requête PostgreSQL, et comment puis-je résoudre ce problème ?

Pourquoi les colonnes de ma fonction renvoyant un ensemble sont-elles concaténées lorsqu'elles sont utilisées dans une requête PostgreSQL, et comment puis-je résoudre ce problème ?

Barbara Streisand
Barbara Streisandoriginal
2024-12-28 17:07:10419parcourir

Why are my set-returning function's columns concatenated when used in a PostgreSQL query, and how can I resolve this?

Colonnes concaténées dans l'enregistrement renvoyées par une fonction

Ce problème survient lors de la tentative d'exécution d'une requête à l'aide d'une fonction renvoyant un ensemble dans une autre requête, ce qui entraîne le retour de toutes les fonctions colonnes étant concaténées en une seule colonne.

Déclaration de fonction

Le Postgres suivant La fonction, account_servicetier_for_day, prend en compte un identifiant de compte et un jour et renvoie des données historiques :

CREATE OR REPLACE FUNCTION account_servicetier_for_day(_accountid integer, _day timestamp without time zone) RETURNS setof account_dsl_history_info AS
$BODY$
DECLARE _accountingrow record;
BEGIN
  Return Query
  Select * From account_dsl_history_info
  Where accountid = _accountid And timestamp <= _day + interval '1 day - 1 millisecond'
  Order By timestamp Desc 
  Limit 1;
END;
$BODY$ LANGUAGE plpgsql;

Problème : colonnes concaténées

Lorsque la fonction est exécutée directement, elle renvoie le résultat attendu avec des colonnes. Cependant, lorsqu'elles sont utilisées dans une requête, les colonnes sont concaténées en une seule :

Select
    '2014-08-12' As day, 0 As inbytes, 0 As outbytes, acct.username, acct.accountid, acct.userid,
    account_servicetier_for_day(acct.accountid, '2014-08-12')
From account_tab acct
Where acct.isdsl = 1
    And acct.dslservicetypeid Is Not Null
    And acct.accountid Not In (Select accountid From dailyaccounting_tab Where Day = '2014-08-12')
Order By acct.username

Solution : Décomposition SQL

Pour décomposer l'enregistrement renvoyé par la fonction en colonnes individuelles, utilisez la syntaxe SQL :

SELECT * FROM account_servicetier_for_day(20424, '2014-08-12');

Postgres 9.3 ou version ultérieure

Pour Postgres 9.3 et versions ultérieures, la requête peut être réécrite à l'aide de JOIN LATERAL :

SELECT '2014-08-12' AS day, 0 AS inbytes, 0 AS outbytes
     , a.username, a.accountid, a.userid
     , f.*   -- but avoid duplicate column names!
FROM   account_tab a
     , account_servicetier_for_day(a.accountid, '2014-08-12') f  -- <-- HERE
WHERE  a.isdsl = 1
AND    a.dslservicetypeid IS NOT NULL
AND    NOT EXISTS (
   SELECT FROM dailyaccounting_tab
   WHERE  day = '2014-08-12'
   AND    accountid = a.accountid
   )
ORDER  BY a.username;

Postgres 9.2 ou version antérieure

Pour Postgres 9.2 ou version antérieure, utilisez une sous-requête pour appeler la fonction de retour d'ensemble et décomposer l'enregistrement dans la requête externe :

SELECT '2014-08-12' AS day, 0 AS inbytes, 0 AS outbytes
     , a.username, a.accountid, a.userid
     , (a.rec).*   -- but be wary of duplicate column names!
FROM  (
   SELECT *, account_servicetier_for_day(a.accountid, '2014-08-12') AS rec
   FROM   account_tab a
   WHERE  a.isdsl = 1
   AND    a.dslservicetypeid Is Not Null
   AND    NOT EXISTS (
       SELECT FROM dailyaccounting_tab
       WHERE  day = '2014-08-12'
       AND    accountid = a.accountid
      )
   ) a
ORDER  BY a.username;

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn