2010-10-12 23 views
3

J'ai une table Oracle qui contient des données comme 'Shiv------Shukla' (considérer '-' comme espace).
Maintenant j'ai besoin d'écrire un programme qui ne laisse qu'un seul espace et supprime tous les autres espaces.Comment faire pour supprimer plus d'un espace dans Oracle

Voici le programme que j'ai réalisé mais il ne me donne pas le résultat attendu.

DECLARE 
    MAX_LIMIT VARCHAR2(50):=NULL; 
    REQ   VARCHAR2(20):=NULL; 
CURSOR C1 IS 
    SELECT * 
    FROM ASSET_Y; 
BEGIN 
    FOR REC IN C1 
    LOOP 
    MAX_LIMIT:=LENGTH(REC.NAME)-LENGTH(REPLACE(REC.NAME,'-')); 
    FOR I IN 1..MAX_LIMIT 
     LOOP 
     UPDATE ASSET_Y 
     SET NAME=REPLACE(REC.NAME,'--','-') 
     WHERE REC.SNO=ASSET_Y.SNO; 
     COMMIT; 
    SELECT ASSET_Y.NAME INTO REQ FROM ASSET_Y WHERE ASSET_Y.SNO=REC.SNO;  
     DBMS_OUTPUT.PUT_LINE(REQ); 
     END LOOP; 
    END LOOP; 
COMMIT; 
END; 
/

Ma table est

SQL> select * from asset_y; 

     SNO NAME     FL 
---------- -------------------- -- 
     1 Shiv------Shukla  y 
     2 Jinesh    y 

après l'exécution de la procédure i m obtenir la sortie suivante.

Shiv---Shukla 
Shiv---Shukla 
Shiv---Shukla 
Shiv---Shukla 
Shiv---Shukla 
Shiv---Shukla 

PL/SQL procedure successfully completed. 

Répondre

2

Avec Oracle 9, vous pouvez écrire votre propre fonction:

CREATE FUNCTION remove_multi_spaces(in_value IN VARCHAR2) 
RETURN VARCHAR2 
AS 
    v_result VARCHAR2(32767); 
BEGIN 
    IF(in_value IS NOT NULL) THEN 
    FOR i IN 1 .. (LENGTH(in_value) - 1) LOOP 
     IF(SUBSTR(in_value, i, 2) <> ' ') THEN 
     v_result := v_result || SUBSTR(in_value, i, 1); 
     END IF; 
    END LOOP; 
    v_result := v_result || SUBSTR(in_value, -1); 
    END IF; 
    RETURN v_result; 
END; 

et l'appeler en une seule mise à jour-déclaration:

UPDATE asset_y 
SET name = replace_multi_spaces(name); 

BTW: Avec vous Oracle 10 pourrait utiliser REGEXP_REPLACE.

+0

Oracle fournit un exemple de la façon de supprimer les espaces en double ici: https://docs.oracle.com/cd/B19306_01/server.102/ b14200/functions130.htm. 'regexp_replace (your_string, '() {2,}', '');' – zundarz

4

Depuis regexp_replace n'est pas disponible dans Oracle 9i, vous pouvez peut-être utiliser des routines OWA_PATTERN pour regex simples REMPLACE:

owa_pattern.change(fStr, '\s+', ' ', 'g'); 

Plus d'informations sur le package OWA_PATTERN peut être trouvé here

Gardez à l'esprit que « \ s "correspondra également aux onglets et aux nouvelles lignes.

+1

'+ 1': C'est plus élégant que ma réponse :) –

1

Une autre façon:

CREATE OR REPLACE 
FUNCTION remove_multi_spaces(in_value IN VARCHAR2) 
RETURN VARCHAR2 IS 
    v_result VARCHAR2(32767) := in_value; 
BEGIN 
    LOOP 
    EXIT WHEN INSTR(v_result,' ') = 0; 
    v_result := REPLACE(v_result, ' ', ' '); 
    END LOOP; 
    RETURN v_result; 
END remove_multi_spaces; 
2

Votre problème est cette partie:

SET NAME=REPLACE(REC.NAME,'--','-') 

Cependant plusieurs fois que vous faites que dans la boucle intérieure, il commence par la même valeur de REC.NAME comme avant. Le changer pour cela le corrigerait:

SET NAME=REPLACE(NAME,'--','-') 

Cependant, il est très inefficace de faire ce travail si la table est grande. Vous pourriez plutôt faire ceci:

BEGIN 
    LOOP 
     UPDATE ASSET_Y 
     SET NAME=REPLACE(NAME,'--','-') 
     WHERE NAME LIKE '%--%'; 

     EXIT WHEN SQL%ROWCOUNT = 0; 
    END LOOP; 
END; 
/
1

Ack loops! Pas besoin de boucler cela

Cela fonctionnera en T-SQL ... malheureusement, je n'ai pas d'environnement pl/sql pour écrire ceci. PL/SQL aura des équivlents à tout ce qui est utilisé ici (je pense que substr au lieu de sous-chaîne et | au lieu de +)

declare @name varchar(200) 
set @name = 'firstword   secondword' 
select left(@name,(patindex('% %',@name)-1)) + ' ' + ltrim(substring(@name,(patindex('% %',@name)+1),len(@name))) 

vous devrez rééquiper à travailler pour Oracle et vous devrez remplacer toute référence à @name à asset_y.name

select left(asset_y.name,(patindex('% %',asset_y.name)-1)) || ' ' || ltrim(substring(asset_y.name,(patindex('% %',asset_y.name)+1),len(asset_y.name))) 

Désolé si elle a gagné Ne courez pas comme ça, comme je l'ai mentionné, il me manque une installation oracle ici pour confirmer ...Juste pour ajouter ... Normalement, je transforme cette requête en une fonction nommée formatname et je l'appelle en sélectionnant formatname (array_y.name) from ... Cela me permet d'inclure une forme de gestion des erreurs. La requête échouera si patindex ('%%', array_v.name) renvoie une valeur nulle ... ce qui signifie qu'il n'y a pas d'espace. Vous pouvez faire la même chose dans une instruction select en utilisant des cas, je suppose:

select case when patindex('% %',array_v.name) > 0 then 
left(asset_y.name,(patindex('% %',asset_y.name)-1)) || ' ' || ltrim(substring(asset_y.name,(patindex('% %',asset_y.name)+1),len(asset_y.name))) 
else asset_y.name 
from...