Как создать функцию StartsWith для типа char (n) с конечным пробелом

Мне нужно создать функцию startwith, которая возвращает true, если столбец базы данных char (n) начинается с некоторых символов, которые могут содержать пробел в конце. Пробелы следует рассматривать как другие символы.

База данных имеет два значения «А» и «АА». Я хочу, чтобы startwith ('A') (без конечного пробела) соответствовал как AA, так и A, но startwith ('A') (с конечным пробелом) соответствовал только A.

Используя образцы данных ниже

startswith( test, 'A')   -- works
startswith( test, 'A  ')  -- returns wrong result : false
StartsWith(test, rpad('A',20) )  -- returns wrong result : false

должен вернуть истину

но

startswith( test, RPAD( 'A', 21))

должен вернуть false, так как в конце проверочной строки есть лишний пробел.

База данных содержит тестовый столбец, который имеет столбец типа char (20), и это не может быть изменено.

Я пробовал код ниже, но он возвращает false.

Как это исправить, чтобы он вернул истину? Использование Postgres начиная с 9.1

Андрус.

CREATE or replace FUNCTION public.likeescape( str text )
--  
https://stackoverflow.com/questions/10153440/how-to-escape-string-while-matching-pattern-in-postgresql
RETURNS text AS $$
SELECT replace(replace(replace($1,'^','^^'),'%','^%'),'_','^_') ;
$$ LANGUAGE sql IMMUTABLE;

CREATE or replace FUNCTION public.StartWith( cstr text, algusosa text )
RETURNS bool AS $$
SELECT $2 is null or $1 like likeescape($2) ||'%' ESCAPE '^' ;
$$ LANGUAGE sql IMMUTABLE;

create temp table test ( test char(20) ) on commit drop;
insert into test values ('A' );
insert into test values ('AA' );

select StartWith(test, 'A ' ) from test

Я также отправил это в список рассылки pgsql-general.


person Andrus    schedule 06.07.2018    source источник
comment
Я не вижу, что не так с первыми тремя примерами. Если test = 'A', test начинается с 'A', не начинается с 'A' и не начинается с 'A ...'. Почему это не так?   -  person 404    schedule 06.07.2018
comment
char (20) дополняется конечными пробелами. Итак, A должен совпадать. База данных имеет два значения «А» и «АА». Я хочу, чтобы startwith ('A') возвращал как AA, так и A, но startwith ('A') возвращает только A. Я обновил вопрос   -  person Andrus    schedule 06.07.2018
comment
Это неверно. CREATE TEMP TABLE t (txt CHAR(20)); INSERT INTO t VALUES ('A'); SELECT '_' || txt || '_' FROM t; возвращает _A_, а SELECT LENGTH(txt) FROM t; возвращает 1   -  person 404    schedule 06.07.2018


Ответы (1)


Из 8.3. Типы персонажей:

Значения типа character физически дополняются пробелами до указанной ширины n и сохраняются и отображаются таким образом. Однако пробелы для заполнения рассматриваются как семантически несущественные. Конечные пробелы не учитываются при сравнении двух значений типа character, и они будут удалены при преобразовании значения character в один из других строковых типов. Обратите внимание, что конечные пробелы семантически значимы в значениях character varying и text, а также при использовании сопоставления с образцом, например LIKE, регулярные выражения.

Обратите внимание, что оба аргумента вашей функции text. Когда вы передаете его, столбец test и литерал 'A ', test теряют конечные пробелы при неявном приведении, тогда как литерал - нет. В вашей функции вы получите что-то вроде

'A' LIKE 'A %' ESCAPE '^'

что не так.

Вы можете перегрузить свою функцию и создать ее копию, где первым аргументом является char, или просто использовать регулярные выражения вместо определения вашей собственной функции, например test ~ '^A ' или rtrim(), пробелы вне char и относиться к ней как к «беспространственной», как rtrim(test) LIKE 'A%'. Я бы предпочел одно из последних.

person sticky bit    schedule 07.07.2018
comment
Можно ли создать функцию StartsWith, которая не удаляет пробелы, когда ей передается char (n) в качестве первого аргумента. n может быть разным для разных запросов. Я пробовал StartsWith ( cstr char(n), StartOfCstrMayContainSpacesAtEnd text ), но это синтаксически неверно. - person Andrus; 07.07.2018
comment
@Andrus: Просто используйте char без (n). - person sticky bit; 07.07.2018