0
votes

Comment effectuer une requête en tant qu'argument dans la fonction PL / PGSQL qui retourne JSON?

J'essaie d'effectuer Select à l'aide de la fonction déjà créée qui retourne JSON qui agrégent dans le tableau JSON, mais je reçois un problème dans la ligne d'utilisation d'une clause Select. Tables J'ai un problème de problème:

create or replace function get_orderitem_by_oi_id(oi_id bigint) returns json
    language plpgsql
as
$FUNCTION$
declare
    found_oi "vertx-jooq-cr".public.order_item;
    book_json json;
    total_oi_price decimal;
    book_price double precision;
begin
    select * into found_oi
    from public.order_item AS oi2
    where oi2.order_item_id = oi_id;

    select public.get_book_by_book_id(public.order_item.book_id::bigint) into book_json
    from public.order_item
    where public.order_item.order_item_id = oi_id;

    select price into book_price
    from book AS b
    inner join public.order_item AS oi USING (book_id);

    total_oi_price = found_oi.amount * book_price;
    return (select json_build_object(
        'order_item_id', found_oi.order_item_id,
        'amount', found_oi.amount,
        'book', book_json,
        'order_id', found_oi.order_id,
        'total_order_item_price', trunc(total_oi_price::double precision::text::numeric, 2)
    ));
end
$FUNCTION$;


12 commentaires

Le curseur est créé par PLPGSQL (Postgres) en arrière-plan pour boucler les résultats de la requête et attribuer les résultats à l'enregistrement Item_Recs. Le problème est que j'ai laissé le dans _Item_id dans et le code du curseur ne peut pas gérer cela. Vous voudrez peut-être créer une fonction simple qui utilise le style pour / boucle pour obtenir une poignée sur la façon dont cela fonctionne.


C'est pourquoi j'ai ajouté le commentaire --- devra modifier pour obtenir votre structure finale JSON. . Je ne sais pas ce qui se passe dans get_orderitem_by_oi_id () ? Je sais que l'élément_recs que vous ajoutez à ordre_items est l'enregistrement avec la commande_Item_id. Si get_orderitem_by_oi_idem_by_oi_id () renvoie un objet / chaîne JSON dont vous devrez ajouter à une structure dans la boucle que vous avez déclarer D et Ensuite, dans la dernière retour ajoutez cette structure à 'ordre_items' .


Bonjour Adrian, j'ai mis à jour ma question concernant vos commentaires pour ma question sous la section update3 , alors jetez un coup d'oeil.


Je ne sais pas comment cette fonction réussit à exécuter. La requête supérieure au début et "verx-jooq-cr" .public.orders devrait le faire échouer. Je dois croire que "get_orderitem_by_oi_id" dans la sortie JSON est là car est renvoyé par get_orderitem_by_oi_id (). Vous n'obtenez qu'un seul élément car comme vous boucle vous remplacez la valeur de commander_items avec la dernière itération de la boucle. Vous devez déclarer quelque chose, dites un tableau, que vous pouvez ajouter chaque Order_Items d'itérations, puis ajouter à "ordre_items" à la fin. Je reçois une chance que je verrai si je peux construire un exemple.


Ajouté une autre méthode pour répondre.


Je ne pense pas que j'ai compris une partie de la requête au-dessus du début et du "Verx-Jooq-Cr" .public.orders devrait le faire échouer. ' ? Ça fonctionne bien. Je vais essayer de modifier mon code à boucle pour que cela enregistre chaque commande_Item et l'appendez dans une matrice de JSON objets ... essayé, mais pas de chance jusqu'à présent. Y a-t-il une méthode appropriée qui est utilisée lors de la fonction de travail avec JSON (afin que je puisse réaliser ce que j'ai mentionné dans la dernière phrase)?


"VERTX-JOOQ-CR" .Public.orders implique la base de données.schema.table Naming. La version communautaire de Postgres ne supporte pas cela, de sorte que cela échouerait à moins que vous n'utilisiez une fourchette de postgres qui le fait.


Je vois..maybe c'est parce que j'utilise Datagramp et il doit avoir à cette nommée qualifiée.


Mais la nommée est à l'intérieur de la fonction et donc à l'intérieur des postgres. Où avez-vous eu ou utilisez-vous Postgres?


J'utilise Postgres 11.8 sur Fedora 30 et les packages Postgres ne sont pas Fedora, mais de PostgreSQL Global Development Group. Vous pouvez voir plus de détails dans ma question et réponses Ici


Hein, je viens d'apprendre quelque chose. Vous pouvez utiliser la base de données_name.schema.table_name tant que Basey_Name est celui que vous êtes dans. Vous ne pouvez pas faire des références de données croisées cependant. Cela signifie que "Verx-Jooq-Cr" est redondant cependant.


Intéressant ... alors j'aurais pu être que quelque chose auparavant n'a pas été configuré à droite Datagramp et je devais mettre "Database_Name.schema. *" Partie pour travailler. Merci d'avoir clarifié cela. BTW, j'ai mis à jour ma réponse en fonction de la réponse et si vous le trouvez bien, veuillez voter +1. Merci d'avance.


3 Réponses :


1
votes

11 commentaires

Merci de votre réponse, mais cela ne fonctionne pas pour mon cas d'utilisation comme première instruction SELECT effectue uniquement une insertion dans un seul élément_id et j'ai besoin de plusieurs identifiants comme Commandes peut contenir plusieurs OrderSitems (veuillez consulter DDL pour les tables en question).


Existe-t-il une autre solution de contournement ... Par exemple, pour charger toutes les commandes_Item_ids dans une matrice et exécuter ultérieurement Public.get_Orderitem_by_oi_id (Order_Item_ID) Fonction pour chaque élément d'un tableau (Commande_Item_ids)?


Voir le changement pour répondre. Évidemment pas testé.


Pourquoi avez-vous supprimé _Item_id dans déclarer section? Je ne vois pas qu'il est utilisé plus tard n'importe où dans le code ... aussi je reçois une erreur lorsque j'essaie d'exécuter la fonction créée (jetez un coup d'œil à ma question de mise à jour sous la section UPDATE1 ).


Parce que c'était pour cas où il y avait un seul ordre_Item_id. Avec la version en boucle, vous n'en avez plus besoin que vous obtenez la commande_Item_id à partir de l'enregistrement. Quant à l'erreur qui était mon erreur. Quand j'ai édité, je pensais avoir supprimé le dans _Item_id et je n'avais pas. Voir la dernière modification :(


Je vois ... Quoi qu'il en soit j'ai essayé votre solution dans la réponse mise à jour et cela n'a pas fonctionné comme il se doit (veuillez consulter ma question mise à jour sous update2 section). BTW, ne devrait pas commander_Item JSON Object déjà être construit en passant sur item_recs.ordr_item_id dans public.get_orderitem_by_oi_id () fonction comme paramètre?


J'ai couru votre méthode alternative, mais cela ne me donne que book_id pendant que j'ai besoin de plus de détails (comme dans des exemples JSON données dans ma question) sur book Table (en plus de son identifiant ).


Je suppose que cela vient de get_orderitem_by_oi_id () que vous ne partageriez pas, donc je devais aller avec une solution plus simple. Si vous pouviez montrer un exemple de ce que get_orderitem_by_oi_id () est / sorties, je pourrais mettre à jour une réponse plus complète.


Pas de problème, j'ai mis à jour ma réponse dans la section update4 , alors veuillez jeter un coup d'oeil. BTW, j'ai déjà donné l'exemple de quel type de sortie get_orderitem_by_oi_id () fonction donne dans le dernier code JSON comme valeur de pour "get_orderitem_by_oi_id": la touche (qui est insérée pour une impair raison en tant que clé).


Exemple générique ajouté avec une matrice pour tenir JSON.


J'ai apporté des modifications dans mon code en suivant des exemples donnés dans votre réponse et réussi à trouver une solution. S'il vous plaît jeter un oeil à la réponse que j'ai posté et ajoutez / suggère si quelque chose peut être amélioré. Merci encore pour votre temps et vos suggestions (merci, j'ai marqué votre réponse comme acceptée) :)



1
votes

Après avoir pris des conseils utiles à partir de @adrianklaver, je suis venu à une solution en déclarant des variables supplémentaires nécessaires pour gérer chaque order_item code> dans la boucle et les requêtes pour produire un résultat final (nécessaire). Voici la solution finale qui fonctionne comme il convient (apportée des modifications de @ Adrianklaver's 2nd Réponse): XXX PRE>

... et voici le résultat JSON que j'ai obtenu: P>

{
  "order_id": 1069,
  "total_price": 136.94,
  "order_date": "2020-06-10T19:57:40.562",
  "user": {
    "user_id": 3,
    "username": "mica"
  },
  "order_items": [
    {
      "order_item_id": 2041,
      "amount": 3,
      "book": {
        "book_id": 6,
        "title": "The Da Vinci Code",
        "price": 29.98,
        "amount": 297,
        "is_deleted": false,
        "authors": [
          {
            "author_id": 8,
            "first_name": "William",
            "last_name": " Shakespeare"
          }
        ],
        "categories": [
          {
            "category_id": 10,
            "name": "Action",
            "is_deleted": false
          }
        ]
      },
      "order_id": 1069,
      "total_order_item_price": 89.94
    },
    {
      "order_item_id": 2042,
      "amount": 2,
      "book": {
        "book_id": 8,
        "title": "The Lord of the Rings",
        "price": 23.5,
        "amount": 298,
        "is_deleted": false,
        "authors": [
          {
            "author_id": 3,
            "first_name": "JRR",
            "last_name": "Tolkien"
          }
        ],
        "categories": [
          {
            "category_id": 9,
            "name": "Crime",
            "is_deleted": false
          }
        ]
      },
      "order_id": 1069,
      "total_order_item_price": 47
    }
  ]
}


1 commentaires

Voir ma deuxième réponse.



1
votes

Qu'est-ce que je vois dans votre réponse. Ceci: xxx pré>

doit être raccourci à ceci: p> xxx pré>

comme vous êtes déjà sur un enregistrement unique. P>

Ceci: p>

Sélectionnez le montant dans OI_Amount à partir de commande_Item en tant que OI où OI.Amount = item_Rec.Amount; code> p>

devrait être: p>

oi_amount = item_recs.amount;


2 commentaires

Ouais, pressé de le faire travailler, j'ai supervisé ces 2 requêtes suffisantes. Merci pour la critique de code. ;)


Code refoulé selon votre (2e) réponse. S'il vous plaît donnez-lui un look et upvote +1 si vous le trouvez fonctionnels. Merci encore