2016-05-26 4 views
1

В Oracle 11g, как я могу определить нулевой символ (chr(0)) в регулярном выражении?Oracle Regular Expression для Null Character

Я ожидаю, что следующее условие оценить, правда, но это не делает:

select case when regexp_like (chr(0), '\0') then 1 else 0 end from dual; 

Мой конкретный случай использования требует обнаружения шаблон нулевых символов в столбце varchar2:

select * from my_table where NOT regexp_like (my_column, '^[\s\0]+$'); 
+2

Нет, * null character * ('chr (0)') - это * not * то же, что и пустая строка, или NULL, которая совершенно иная. –

+1

@JeffreyKemp: Я думаю, вы имеете в виду 'NUL', а не' NULL'? Несмотря на это, они не совпадают - согласились. –

+0

Нет, что вы подразумеваете под NUL? –

ответ

1

Невозможно идентифицировать только нулевой символ в регулярном выражении Oracle. Oracle's Regular Expression reference documentation указывает, какие регулярные выражения поддерживаются, и не упоминает о поддержке метасимвола или выражения, которое идентифицировало бы нулевой символ (хотя поддерживается подмножество других стандартных метасимволов). Мои тесты подтвердили это, так же как и некоторые последующие тесты, выполненные другими в этом потоке.

Хотя ответ на этот вопрос заключается в том, что это невозможно, некоторые из других ответов могут помочь удовлетворить другие случаи использования. В частности, см. Это answer, в котором предлагается использовать класс [[:cntrl:]]. Это будет определять нулевые символы в регулярном выражении, хотя оно также будет соответствовать другим символам класса.

1

Вы можете использовать класс символов [:cntrl:].

SELECT 
    CASE 
    WHEN regexp_like (chr(0), '[[:cntrl:]]') 
    THEN 1 
    ELSE 0 
    END control_chr 
FROM dual; 

CONTROL_CHR 
----------- 
1 
+0

Спасибо. Этого может быть достаточно для моего использования; однако класс '[: cntrl:]' также включает в себя другие символы, кроме нулевого символа, например. 'CHR (7)'. Есть ли способ обнаружить только нулевой символ? – shelley

1

Я сделал несколько исследований для этого вопроса. chr (0) - вещь, которая повсюду вызывает хаос.

Сначала я создал таблицу, вставил в нее строку с chr (0) и попытался найти ее с помощью regexp_like.

CREATE TABLE t1(col1 VARCHAR2(10)); 
INSERT INTO t1 VALUES('' || chr(0) || '5678'); 
SELECT CASE WHEN REGEXP_LIKE(col1,CHR(0)) THEN 1 ELSE 0 END op,col1, dump(col1) FROM t1; 

Выход был ниже -

op  col1  dump(col1) 
---- -----  ------------------------------------------------- 
1 Typ=1 Len=10: 48,49,50,51,52,0,53,54,55,56 

Как вы можете видеть, дамп показывает фактически CHR (0) находится там, хотя, показывая строку на экране, инструмент считает CHR (0) как нулевой ограничитель и не показывает остальных. Таким образом, казалось, что regexp_like фактически находит соответствие для chr (0) внутри строки.

Но, к моему полному разочарованию, я обнаружил, что даже строка без chr (0) вернет тот же результат.

DELETE FROM t1; 
INSERT INTO t1 VALUES(''); 
SELECT CASE WHEN REGEXP_LIKE(col1,CHR(0)) THEN 1 ELSE 0 END op,col1, dump(col1) FROM t1; 

op  col1   dump(col1) 
----- -------  ---------------------------------------------------- 
1 Typ=1 Len=10: 48,49,50,51,52,53,54,55,56,57 

Так что есть что-то рыболовное для обработки chr (0). Я опубликовал следующий вопрос и получил объяснение по тому же вопросу. chr (0) является строкой с нулевой длиной, всякий раз, когда мы пытаемся найти ее внутри строки, она, по-видимому, найдет ее повсюду, фактически найдя ее на самом деле нигде.

Кажется, что невозможно найти chr (0) в строке. См. Ответ от MTO.

CHR(0) in REGEXP_LIKE

+0

Какую версию базы данных Oracle вы пробовали? Он отлично работает для меня на 11gR2 - chr (0) считается просто другим персонажем, и он появляется без проблем. Тем не менее, chr (0) обрабатывается специально regexp_like, поэтому я бы использовал LIKE вместо этого, который правильно его обрабатывает. –

1

Вы можете использовать LIKE или INSTR с CHR(0) обнаружить его, но REGEXP_LIKE не будет работать, потому что он лечит CHR(0) специально.

create table t1 (col1 varchar2(10)); 

insert into t1 values (''||chr(0)||'5678'); 

insert into t1 values ('X5678'); 

select case when col1 like '%'||chr(0)||'%' then 1 else 0 end r, col1, dump(col1) from t1; 

select case when instr(col1,chr(0)) > 0 then 1 else 0 end r, col1, dump(col1) from t1; 

Обе вышеуказанные запросы показывают следующие результаты:

enter image description here

select case when regexp_like(col1,chr(0)) then 1 else 0 end r, col1, dump(col1) from t1; 

Это дает следующий результат:

enter image description here

Вам нужно быть осторожным, потому что некоторые клиенты остановятся когда они сталкиваются с CHR(0). Например, когда я попытался скопировать и вставить из сетки результатов запроса SQL Developer, он остановился на этом этапе.

+0

«REGEXP_LIKE' не будет работать, потому что он обрабатывает' CHR (0) 'специально» - есть ли у вас какие-либо ссылки для этого? К сожалению, ни «LIKE», ни «INSTR» не будут работать для моего использования; Мне нужно регулярное выражение для поиска определенных шаблонов, содержащих нулевые символы. – shelley

+0

@shelley - это уже было в другом ответе. Обратите внимание на ответ MT0 здесь: http://stackoverflow.com/questions/37461369/chr0-in-regexp-like –

+0

Вы можете заменить CHR (0) 'на другую строку символов перед вызовом REGEXP_LIKE, чтобы обойти это. –