2010-10-22 5 views
3

Script ShellPour lire le fichier et mettre des valeurs dans la clause WHERE via script shell

#! /bin/bash 
sqlplus -s <username>/<passwd>@dbname << EOF 
set echo on 
set pagesize 0 
set verify off 
set lines 32000 
set trimspool on 
set feedback off 
SELECT * 
    FROM <dbname>.<tablename1> tr 
    LEFT JOIN <tablename2> t2 ON t2.id2 = tr.id1 
    LEFT JOIN <tablename3> t3 ON t3.id2 = tr.id1 
    LEFT JOIN <tablename4> t4 ON t4.id2 = tr.id1 
WHERE tr.TIMESTAMP > SYSDATE - 75/1440 
    AND tr.TIMESTAMP <= SYSDATE - 15/1440 
    AND t2.value in (value1, value2, etc...) 
ORDER BY timestamp; 

exit; 
EOF 

Maintenant, le but est de lire 32000 valeurs dans t2.value colonne. Ces valeurs ne sont que des nombres comme 1234, 4567, 1236, etc. Je suppose que je devrais mettre ces nombres dans un fichier séparé, puis lire ce fichier dans t2.value. Mais je veux que le SQL soit excuté seulement une fois pas 32000 fois. pouvez-vous s'il vous plaît conseiller comment est-ce possible? Comment puis-je obtenir les valeurs (séparées par des virgules) dans t2.value (par une boucle, en lisant la ligne probablement)?

Répondre

0

Vous pouvez créer une virgule liste séparée à partir du fichier qui contient tous les numéros un par ligne comme:

t2val=$(cat your_file_with_numbers | tr '\n' ',' | sed 's/,$//') 

Ensuite, vous pouvez utiliser cette $t2val variable:

.... 
and t2.value in ("$t2val") 

Nous remplaçons le \n entre les lignes avec une virgule et en supprimant la dernière virgule qui, comme aucun numéro suivant, va créer une erreur de syntaxe dans Oracle.

+0

Je suis l'erreur sur erreur de sortie standard: ORA-00972: identifiant est trop long – ErAB

+0

ORA-00972 vient quand vous avez utilisé un identifiant très long,> 38 personnages. Mais nous ne changeons aucun identifiant (colonne, nom de table) n'importe où. Quels changements avez-vous faits? – codaddict

+0

Je vais coller le script complet. – ErAB

1

vous pouvez utiliser SQL * Loader pour charger ces valeurs dans une table temporaire que vous avez créée dans un premier temps avec un index sur sa seule colonne.

sqlldr user/password%@sid control=ctl_file 

Contenu de ctl_file:

load data 
infile * 
append 
into table MY_TEMP_TABLE 
fields terminated by ";" optionally enclosed by '"' 
(
    column1 
) 
begindata 
"value1" 
"value2" 
[...] 

(guillemets doubles sont facultatifs et inutiles pour les numéros

ensuite modifier votre requête avec:.

AND t2 in (SELECT column1 FROM my_temp_table) 

et DROP my_temp_table après.

0
#!/bin/bash 
    2 t2val=$(cat /home/trnid | tr '\n' ',' | sed 's/,$//') 
    3 sqlplus -s <username>/<passwd>@dbname > /home/file << EOF 
    4 set echo on 
    5 set pagesize 0 
    6 set verify off 
    7 set lines 32000 
    8 set trimspool on 
    9 set feedback off 
10 SELECT * 
     FROM <dbname>.<tablename1> tr 
     LEFT JOIN <tablename2> t2 ON t2.id2 = tr.id1 
     LEFT JOIN <tablename3> t3 ON t3.id2 = tr.id1 
     LEFT JOIN <tablename4> t4 ON t4.id2 = tr.id1 
     WHERE tr.TIMESTAMP > SYSDATE - 75/1440 
     AND tr.TIMESTAMP <= SYSDATE - 15/1440 
     and t2.value in ("t2val") 
     order by timestamp; 
26 exit; 
27 EOF 

trnid file has total of 32000 lines (each number on separate line). The length of each number is 11 digits. 

Je viens de passer pour voir différentes Erreur:

entrée tronquée à 7499 caractères SP2-0027: entrée est trop longue (> 2499 caractères) - Ligne ignorée Entrée tronquée à 7499 caractères SP2-0027 : L'entrée est trop longue (> 2499 caractères) - ligne ignorée.

L'erreur précédente J'ai obtenu bcoz j'ai inséré les nombres dans le fichier trnid séparés par des virgules et dans la ligne différente. Dans le cas, je l'ai utilisé que la commande:

t2val=$(cat /home/trnid) 
Questions connexes