J'ai essayé d'écrire la requête de jointure interne suivante à l'aide d'une base de données Oracle:
SELECT Employee.EMPLID as EmpID,
Employee.FIRST_NAME AS Name,
Team.DEPARTMENT_CODE AS TeamID,
Team.Department_Name AS teamname
FROM PS_TBL_EMPLOYEE_DETAILS Employee
INNER JOIN PS_TBL_DEPARTMENT_DETAILS Team
ON Team.DEPARTMENT_CODE = Employee.DEPTID
Cela donne l'erreur ci-dessous:
INNER JOIN PS_TBL_DEPARTMENT_DETAILS Team ON Team.DEPARTMENT_CODE = Employee.DEPTID
*
ERROR at line 4:
ORA-00904: "TEAM"."DEPARTMENT_CODE": invalid identifier
Le DDL d'une table est:
CREATE TABLE "HRMS"."PS_TBL_DEPARTMENT_DETAILS"
(
"Company Code" VARCHAR2(255),
"Company Name" VARCHAR2(255),
"Sector_Code" VARCHAR2(255),
"Sector_Name" VARCHAR2(255),
"Business_Unit_Code" VARCHAR2(255),
"Business_Unit_Name" VARCHAR2(255),
"Department_Code" VARCHAR2(255),
"Department_Name" VARCHAR2(255),
"HR_ORG_ID" VARCHAR2(255),
"HR_ORG_Name" VARCHAR2(255),
"Cost_Center_Number" VARCHAR2(255),
" " VARCHAR2(255)
)
SEGMENT CREATION IMMEDIATE PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS
Votre problème, ce sont ces guillemets pernicieux.
SQL> CREATE TABLE "APC"."PS_TBL_DEPARTMENT_DETAILS"
2 (
3 "Company Code" VARCHAR2(255),
4 "Company Name" VARCHAR2(255),
5 "Sector_Code" VARCHAR2(255),
6 "Sector_Name" VARCHAR2(255),
7 "Business_Unit_Code" VARCHAR2(255),
8 "Business_Unit_Name" VARCHAR2(255),
9 "Department_Code" VARCHAR2(255),
10 "Department_Name" VARCHAR2(255),
11 "HR_ORG_ID" VARCHAR2(255),
12 "HR_ORG_Name" VARCHAR2(255),
13 "Cost_Center_Number" VARCHAR2(255),
14 " " VARCHAR2(255)
15 )
16 /
Table created.
SQL>
Oracle SQL nous permet d'ignorer la casse des noms d'objet de base de données à condition que nous les créions avec des noms en majuscules ou sans guillemets. Si nous utilisons des majuscules ou des minuscules dans le script et que les identificateurs sont entourés de guillemets doubles, nous sommes condamnés à utiliser des guillemets doubles et la casse précise chaque fois que nous faisons référence à l'objet ou à ses attributs:
SQL> select count(*) from PS_TBL_DEPARTMENT_DETAILS
2 where Department_Code = 'BAH'
3 /
where Department_Code = 'BAH'
*
ERROR at line 2:
ORA-00904: "DEPARTMENT_CODE": invalid identifier
SQL> select count(*) from PS_TBL_DEPARTMENT_DETAILS
2 where "Department_Code" = 'BAH'
3 /
COUNT(*)
----------
0
SQL>
tl; dr
n'utilisez pas de guillemets dans les scripts DDL
(Je connais la plupart des générateurs de code tiers, mais ils sont suffisamment disciplinés pour mettre tous leurs noms d'objet dans UPPER CASE.)
Dans mon cas, cette erreur s'est produite, en raison de l'absence d'existence d'un nom de colonne dans la table.
Quand j'ai exécuté "describe tablename
", je n'ai pas pu trouver la colonne spécifiée dans le fichier de mappage hbm.
Après avoir modifié la table, cela a bien fonctionné.
Pour info, dans ce cas, la cause était un nom de colonne de casse mixte dans le DDL pour la création de table.
Toutefois, si vous mélangez l'ancien style et les jointures ANSI, vous risquez d'obtenir le même message d'erreur même lorsque la DDL a été correctement exécutée avec le nom de la table en majuscule. C'est ce qui m'est arrivé et Google m'a envoyé sur cette page stackoverflow. J'ai donc pensé partager avec vous depuis mon arrivée ici.
--NO PROBLEM: ANSI syntax
SELECT A.EMPLID, B.FIRST_NAME, C.LAST_NAME
FROM PS_PERSON A
INNER JOIN PS_NAME_PWD_VW B ON B.EMPLID = A.EMPLID
INNER JOIN PS_HCR_PERSON_NM_I C ON C.EMPLID = A.EMPLID
WHERE
LENGTH(A.EMPLID) = 9
AND LENGTH(B.LAST_NAME) > 5
AND LENGTH(C.LAST_NAME) > 5
ORDER BY 1, 2, 3
/
--NO PROBLEM: OLD STYLE/deprecated/traditional Oracle proprietary join syntax
SELECT A.EMPLID, B.FIRST_NAME, C.LAST_NAME
FROM PS_PERSON A
, PS_NAME_PWD_VW B
, PS_HCR_PERSON_NM_I C
WHERE
B.EMPLID = A.EMPLID
and C.EMPLID = A.EMPLID
and LENGTH(A.EMPLID) = 9
AND LENGTH(B.LAST_NAME) > 5
AND LENGTH(C.LAST_NAME) > 5
ORDER BY 1, 2, 3
/
Les deux instructions SQL ci-dessus sont équivalentes et ne génèrent aucune erreur.
Lorsque vous essayez de les mélanger, vous pouvez avoir de la chance ou obtenir un Oracle qui a une erreur ORA-00904.
--LUCKY: mixed syntax (ANSI joins appear before OLD STYLE)
SELECT A.EMPLID, B.FIRST_NAME, C.LAST_NAME
FROM
PS_PERSON A
inner join PS_HCR_PERSON_NM_I C on C.EMPLID = A.EMPLID
, PS_NAME_PWD_VW B
WHERE
B.EMPLID = A.EMPLID
and LENGTH(A.EMPLID) = 9
AND LENGTH(B.FIRST_NAME) > 5
AND LENGTH(C.LAST_NAME) > 5
/
--PROBLEM: mixed syntax (OLD STYLE joins appear before ANSI)
--http://sqlfascination.com/2013/08/17/Oracle-ansi-vs-old-style-joins/
SELECT A.EMPLID, B.FIRST_NAME, C.LAST_NAME
FROM
PS_PERSON A
, PS_NAME_PWD_VW B
inner join PS_HCR_PERSON_NM_I C on C.EMPLID = A.EMPLID
WHERE
B.EMPLID = A.EMPLID
and LENGTH(A.EMPLID) = 9
AND LENGTH(B.FIRST_NAME) > 5
AND LENGTH(C.LAST_NAME) > 5
/
Et le message d'erreur inutile qui ne décrit pas vraiment le problème:
>[Error] Script lines: 1-12 -------------------------
ORA-00904: "A"."EMPLID": invalid identifier Script line 6, statement line 6,
column 51
J'ai pu trouver des recherches à ce sujet dans l'article suivant du blog:
Dans mon cas, j'essayais de convertir manuellement les jointures de style ancien en jointes de style ANSI, et ce, de manière incrémentielle, une table à la fois. Cela semble avoir été une mauvaise idée. Au lieu de cela, il est probablement préférable de convertir toutes les tables en même temps, ou de mettre en commentaire une table et ses conditions where dans la requête d'origine afin de la comparer à la nouvelle requête ANSI que vous écrivez.
DEPARTMENT_CODE n'est pas une colonne qui existe dans la table Team. Vérifiez le DDL de la table pour trouver le nom de colonne approprié.
Êtes-vous sûr d'avoir une colonne DEPARTEMENT_CODE dans votre table PS_TBL_DEPARTMENT_DETAILS
Plus d'informations à propos de votre ERREUR
ORA-00904: chaîne: identificateur non valide Cause: le nom de colonne entré est manquant ou invalide . Action: Entrez un nom de colonne valide. Un nom de colonne valide doit commencer par un lettre, être inférieur ou égal à 30 caractères et composé uniquement de caractères alphanumériques et les caractères spéciaux $, _ et # . S'il contient d'autres caractères, il doit être placé entre d double guillemets. Ce n'est peut-être pas un mot réservé.
Assurez-vous également que l'utilisateur à l'origine de la requête dispose des autorisations nécessaires.
Pour les requêtes sur les tables, vous devez accorder l’autorisation SELECT.
Pour les requêtes sur d'autres types d'objet (par exemple, procédures stockées), vous devez accorder l'autorisation EXECUTE.
J'ai eu cette erreur en essayant de sauver une entité via JPA.
C'était parce que j'avais une colonne avec l'annotation @JoinColumn
qui n'avait pas d'annotation @ManyToOne
.
L'ajout de @ManyToOne
a résolu le problème.
J'ai eu la même exception dans JPA 2 en utilisant Eclipse link. J'avais une classe @embedded avec une relation un à un avec une entité. Par erreur, dans la classe intégrée, j'avais aussi l'annotation @Table ("TRADER"). Lorsque la base de données a été créée par le JPA à partir des entités, elle a également créé une table TRADER (ce qui était une erreur car l'entité Trader était incorporée à l'entité principale) et l'existence de cette table était à l'origine de l'exception ci-dessus chaque fois que j'essayais de: persiste mon entité. Après avoir supprimé la table TRADER, l'exception a disparu.
Assurez-vous qu'il n'y a pas/après vos instructions DDL.
Je passais les valeurs sans les guillemets. Une fois que j'ai passé les conditions à l'intérieur des guillemets simples a fonctionné comme un charme.
Select * from emp_table where emp_id=123;
au lieu de ce qui précède, utilisez ceci:
Select * from emp_table where emp_id='123';