Как удалить более одного пробела в Oracle - PullRequest
3 голосов
/ 12 октября 2010

У меня есть таблица Oracle, которая содержит такие данные, как 'Shiv------Shukla' (рассмотрим '-' как пробел). Теперь мне нужно написать программу, которая оставляет только один пробел и удаляет все остальные пробелы.

Вот программа, которую я создал, но она не дает ожидаемого результата.

 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;
/

Мой столик

SQL> select * from asset_y;

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

после выполнения процедуры я получаю следующий вывод.

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

PL/SQL procedure successfully completed.

Ответы [ 5 ]

4 голосов
/ 12 октября 2010

Поскольку regexp_replace недоступно в Oracle 9i, возможно, вы можете использовать процедуры owa_pattern для простой замены регулярных выражений:

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

Более подробную информацию о пакете owa_pattern можно найти здесь

Имейте в виду, что "\ s" будет также соответствовать символам табуляции и новой строки.

2 голосов
/ 12 октября 2010

Ваша проблема заключается в этой части:

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

Сколько бы раз вы ни делали это во внутреннем цикле, он начинается с того же значения REC.NAME, что и раньше.Если изменить его на это, то это исправит:

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

Однако, если таблица большая, это довольно неэффективный способ выполнить эту работу.Вместо этого вы можете сделать это:

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

      EXIT WHEN SQL%ROWCOUNT = 0;
   END LOOP;
END;
/
2 голосов
/ 12 октября 2010

С Oracle 9 вы можете написать свою собственную функцию:

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;

и вызвать ее в одном выражении обновления:

UPDATE asset_y
SET name = replace_multi_spaces( name );

Кстати: с Oracle 10 выможно использовать REGEXP_REPLACE.

1 голос
/ 14 октября 2010

Ack петли!Не нужно зацикливать это

Это будет работать в T-SQL ... к сожалению, у меня нет среды pl / sql, чтобы написать это. PL / SQL будет иметь эквиваленты всему, что здесь используется (я думаю, что вместоподстрока и | вместо +)

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

Вам придется переоборудовать ее для работы в Oracle и вам нужно заменить любую ссылку на @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)))

Извините, если он не будет работать как есть, как я уже говорил, мне не хватает здесь установки oracle для подтверждения ...

Просто для добавления ... Я обычно превращаю этот запрос выше в функцию с именем formatname ивызвать его как select formatname (array_y.name) из ... Это позволяет мне включить некоторую форму обработки ошибок.Запрос не будет выполнен, если patindex ('%%', array_v.name) вернет значение NULL ... что означает отсутствие пробела.Вы можете сделать то же самое в операторе выбора, используя случаи, которые я предполагаю:

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...
1 голос
/ 12 октября 2010

Другой способ:

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;
...