0
votes

Oracle SQL - Le code non nul ne fonctionne pas

J'essaie de récupérer le montant monétaire associé aux ID de projet, mais je veux uniquement des données où un ID de projet existe (non vide)

Lorsque je tape mon code SQL ci-dessous ...

SELECT project_id, monetary_amount, journal_line_date 
FROM PS_JRNL_LN 
where project_id is not null
  and journal_line_date BETWEEN to_date ('2020/01/01','yyyy/mm/dd') 
                            AND TO_DATE ('2020/03/04','yyyy/mm/dd')

cette requête fonctionne cependant, j'obtiens toujours des valeurs vides dans mon résultat


9 commentaires

Aidez-nous à vous aider - veuillez partager quelques exemples de données et le résultat que vous essayez d'obtenir pour cela


Qu'entendez-vous par «vierge»? Voulez-vous dire nul, espaces, etc.?


Comme le suggère @TheImpaler, ce que vous voyez comme "nul" n'est très probablement pas "nul", mais des chaînes non nulles constituées entièrement d '"espaces blancs" (très probablement des espaces et / ou des tabulations). C'est une pratique très courante (mais très fausse) de saisir un seul espace comme "espace réservé" pour null . (J'ai vu cela surtout dans les produits PS ...)


Bien sûr, nous ne connaissons pas vos données, mais à première vue, je m'attendrais à ce qu'une colonne nommée PROJECT_ID soit NOT NULL, et probablement des contrôles très stricts sur ce qui est autorisé à y être placé en premier lieu - donc éliminant également juste les espaces. Le fait que vous rencontrez ce problème est fortement évocateur d'une grave lacune dans le modèle de données ou le code de l'application.


@EdStevens - vous supposez que project_id est la clé primaire de cette table. Je doute que ce soit le cas ici. Quant au "modèle de données", je crois que PeopleSoft lui-même est le coupable. (Notez le PS_ de début dans le nom de la table.) D'après ce qu'on m'a dit, la valeur par défaut est que toutes les colonnes des tables PS soient non nulles , à l'exception des colonnes de date . Un seul espace est par ailleurs utilisé comme substitut. C'est une pratique idiote, d'accord - mais probablement pas une pratique sur laquelle le PO a quelque chose à dire. Et notez que PeopleSoft est (maintenant) la propriété d'Oracle!


@mathguy - Vous avez raison. Je n'avais pas compris qu'il s'agissait d'une table PS. D'un autre côté, je n'ai pas vraiment supposé que PROJECT_ID était un PK. Même si la table utilise une clé de substitution (que j'ai prise en compte dans ma réflexion), toute colonne nommée SOMETHING_ID (notant le 'ID') indique fortement qu'il s'agit de données critiques pour lesquelles NOT NULL serait appelé.


Quel est le type de données de la colonne project_id ?


@EdStevens - "id" peut également indiquer une clé étrangère, qui peut très bien être null . Par exemple: "manager_id" pointant vers "employee_id"; L'identifiant du manager peut être nul (pour le président ou le PDG de la société).


@mathguy - eh bien, je n'ai pas dit "définitif", juste très suggestif .. ;-)


5 Réponses :


0
votes

Vous n'avez pas de valeurs nulles mais des espaces vides, ajoutez ci-dessous dans votre requête

 SELECT project_id, monetary_amount, 
  journal_line_date 
  FROM PS_JRNL_LN 
    where ( project_id is not null or
   ( project_id is not 
     null   
    and  LTRIM( RTrim(project_id)) not 
       like '') 
     and 
     journal_line_date BETWEEN 
     to_date ('2020/01/01','yyyy/mm/dd') 
                        AND TO_DATE 
   ('2020/03/04','yyyy/mm/dd')


2 commentaires

ltrim (rtrim (str)) est identique à trim (str) . Mais votre requête comporte en fait une erreur: comparer à null avec l'opérateur not like est tout simplement faux.


Vous comparez toujours avec pas comme '' - c'est incorrect. Doit être n'est pas nul . (Et il semble que vous n'ayez pas compris ce que j'ai dit à propos de l'application à la fois de ltrim et de rtrim .)



0
votes

Voici quelque chose qui peut vous aider à découvrir ce qui se passe dans la colonne project_id . (Très probablement, un tas de valeurs '' , c'est-à-dire une chaîne non vide composée d'un seul espace.)

where project_id != ' '

DUMP s'affiche vous exactement ce qui est stocké dans votre table. 32 est le code ASCII pour un seul espace; 9 (ou 09) est le code de la tabulation horizontale. J'espère que vous obtiendrez des lignes où la colonne DUMP montre un seul caractère, avec le code 32. Mais - qui sait; vous pouvez également trouver d'autres choses.

Cela vous aidera à comprendre ce qu'il y a dans la colonne. (Vous pouvez également vérifier décrire ps_jrnl_ln - vous découvrirez peut-être que la colonne est déclarée non nulle !!!)

Si vous trouvez un tas de lignes où l'ID du projet est un seul espace, bien sûr, dans votre requête réelle, vous devrez remplacer

where ltrim(project_id, chr(32) || chr(9)) is not null

par

where project_id is not null

Ou, peut-être, si en effet un seul espace est utilisé comme espace réservé pour null:

select project_id, dump(project_id)
from   ps_jrnl_ln
where  ltrim(project_id, chr(32) || chr(9)) is null
  and  project_id is not null
;


0 commentaires

0
votes

Peu de choses que vous devez mettre en œuvre dans la conception de votre table pour éviter le problème en premier lieu que de lutter avec les données:

  1. Ajoutez une contrainte NOT NULL à la colonne.
  2. Ajoutez une contrainte CHECK pour empêcher les caractères indésirables tels que les espaces blancs, etc. et autoriser uniquement les données que vous souhaitez charger.
  3. Si vous ne souhaitez pas de contrainte de vérification, gérez-la lors du chargement des données à l'aide de TRIM .
  4. Si nécessaire, faites de la colonne PROJECT_ID la clé primaire, cela n'autoriserait implicitement pas les valeurs NULL. Habituellement, la colonne ID dans un tableau suggère qu'il s'agit d'une clé primaire, mais cela peut varier selon votre cas d'utilisation.

Si vous n'êtes pas autorisé à modifier la conception en n'effectuant aucune des actions ci-dessus, vous pouvez au moins gérer l'insertion de données au niveau de l'application où vous pourriez les prendre comme entrée.


0 commentaires

0
votes

Essayez d'utiliser la condition de filtre:

ltrim(rtrim(project_id)) <> ''


2 commentaires

Pourquoi ltrim, rtrim les deux quand vous pourriez simplement utiliser la garniture?


Et '' est un NULL, vous ne pouvez pas le comparer comme <> '' . Vous devez utiliser IS NOT NULL.



0
votes

Inner joint cette table journal à la source de vérité pour les ID de projet. En supposant qu'il n'y ait pas d'identifiant "vide" dans ce tableau, alors vous n'obtiendrez pas de "blanc" dans votre résultat.

par exemple

SELECT j.project_id, j.monetary_amount, j.journal_line_date 
FROM PS_JRNL_LN J

  INNER JOIN PROJECT_MASTER P ON j.project_id = p.id /* should remove "blanks" */

where j.journal_line_date >= to_date ('2020/01/01','yyyy/mm/dd') 
and  j.journal_line_date < TO_DATE ('2020/03/05','yyyy/mm/dd')

Notez également que je n'utilise jamais entre pour les plages de dates, le modèle ci-dessus utilisant > = & est plus fiable (car il fonctionne quelle que soit la précision temporelle des données) .


0 commentaires