Bonjour,

Voici mon cas.

Je reçois un fichier contenant des données de produits de la forme suivente (je simplifie le fichier et ma table pour que ce soit + lisible car le fichier a normalement 35 champs et la table 44 champs).

Code : Sélectionner tout - Visualiser dans une fenêtre à part
code produit|nom produit|type de colis|longueur|largeur|
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
 
ABC|blabla|1|15|21|
ABC|blabla|2|17|13|
ABC|blabla|3|5|11|
PLO|plouplouf|1|40|54|
PLO|plouplouf|2|38|48|
PLO|plouplouf|3|42|59|
Voici un tableau qui permet de mieux visualiser les données (sachant que ce n'est qu'une représentation, pas une table de travail) :



Voici la table que je souhaite remplir :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
TABLE_PRODUITS (
	DAT_TRAIT	timestamp  NOT NULL,   
	PRO_CODE	varchar2(17) NOT NULL,
	PRO_LIB	  varchar2(70),
	LENGTH_1 number(12,3),
	LENGTH_2 number(12,3),
	LENGTH_3 number(12,3),
	WIDTH_1	number(12,3),
	WIDTH_2	number(12,3),
	WIDTH_3	number(12,3)
)
NB : DAT_TRAIT est rempli par un trigger qui avant chaque INSERT dans la table insère "systimestamp".

Et le résultat que je souhaite obtenir (1 seule ligne par produit) :



J'ai donc écrit le fichier de contrôle suivant :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
LOAD DATA
INFILE '/my_data.dat'
BADFILE '/my_data.bad'
APPEND
PRESERVE BLANKS  
 
-- COLIS 1
INTO TABLE TABLE_PRODUITS
when TYPE_COLIS = '1' 
FIELDS TERMINATED BY '|'
TRAILING NULLCOLS
 (
	PRO_CODE "upper(trim(:PRO_CODE))",
	PRO_LIB "upper(trim(:PRO_LIB))", 
	TYPE_COLIS FILLER,
	LENGTH_1 nullif LENGTH_1='0' "replace(:LENGTH_1, ',', '.')", 
	WIDTH_1 nullif WIDTH_1='0' "replace(:WIDTH_1, ',', '.')"
)
 
-- COLIS 2
INTO TABLE TABLE_PRODUITS
when TYPE_COLIS = '2' 
FIELDS TERMINATED BY '|'
TRAILING NULLCOLS
 (
 	PRO_CODE "upper(trim(:PRO_CODE))",
	PRO_LIB "upper(trim(:PRO_LIB))", 
	TYPE_COLIS FILLER,
	LENGTH_2 nullif LENGTH_2='0' "replace(:LENGTH_2, ',', '.')", 
	WIDTH_2 nullif WIDTH_2='0' "replace(:WIDTH_2, ',', '.')"
)
 
-- COLIS 3
INTO TABLE TABLE_PRODUITS
when TYPE_COLIS = '3' 
FIELDS TERMINATED BY '|'
TRAILING NULLCOLS
 (
 	PRO_CODE "upper(trim(:PRO_CODE))",
	PRO_LIB "upper(trim(:PRO_LIB))", 
	TYPE_COLIS FILLER,
	LENGTH_3 nullif LENGTH_3='0' "replace(:LENGTH_3, ',', '.')", 
	WIDTH_3 nullif WIDTH_3='0' "replace(:WIDTH_3, ',', '.')"
)

Actuellement avec ce fichier de contrôle j'obtiens cela :


Je sais qu'il faut utiliser "POSITION(x:y)" pour que SQL Loader reparcoure les enregistrements depuis le début.
J'ai donc ajouté POSITION(1:3)au champ PRO_CODE comme suit

Code : Sélectionner tout - Visualiser dans une fenêtre à part
PRO_CODE POSITION(1:3) "upper(trim(:PRO_CODE))" ,

Mais cela n'a rien changé.

Par divers tests sur des tables d'exemple (voir ce topic) j'ai cru comprendre qu'il fallait que le POSITION(x:y) concerne le champ de la clause WHEN.
Déjà, est ce que cette constatation est vraie ?

Si oui, je ne peux pas mettre "POSITION(x:y)" au champ TYPE_COLIS car certains champs précédant TYPE_COLIS (notamment PRO_LIB) sont de longueur variable !

J'ai donc penser à ajouter une clause au when comme suit :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
when TYPE_COLIS = '3' 
and PRO_CODE <> '000000' -- (ou PRO_CODE not null, je ne sais pas la syntaxe)
Mais j'ai testé, cela ne fonctionne pas mieux, j'obtiens toujours le même résultat.
Dans les logs, je vois que SQLLoader plante sur un champ que je ne vous ai pas mis (ORA-01401: inserted value too large for column) alors que la colonne est un varchar2(3) et qua la valeur à insérer est "01"...
C'est idem en mettant la clause sur le PRO_CODE en premier ..

Est-ce que qqun pourrait m'aider ?

D'avance merci !